package com.zmj.sy.mom.srv.aps.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.zmj.sy.mom.srv.aps.bean.bo.AreaDetail;
import com.zmj.sy.mom.srv.aps.bean.entity.base.BaseEntity;
import com.zmj.sy.mom.srv.aps.bean.entity.lantekpre.LantekNestExcess;
import com.zmj.sy.mom.srv.aps.bean.entity.lantekpre.LantekNestPart;
import com.zmj.sy.mom.srv.aps.bean.entity.lantekpre.LantekNestPlate;
import com.zmj.sy.mom.srv.aps.bean.entity.lantekpre.LantekPushPackage;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.*;
import com.zmj.sy.mom.srv.aps.bean.entity.order.*;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.DictData;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.Group;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.LogContent;
import com.zmj.sy.mom.srv.aps.bean.entity.third.*;
import com.zmj.sy.mom.srv.aps.bean.vo.base.*;
import com.zmj.sy.mom.srv.aps.bean.vo.lantek.PlatePreNestStockVo;
import com.zmj.sy.mom.srv.aps.bean.vo.lantek.PlatePreNormVo;
import com.zmj.sy.mom.srv.aps.bean.vo.lantek.PlatePreStockVo;
import com.zmj.sy.mom.srv.aps.bean.vo.report.*;
import com.zmj.sy.mom.srv.aps.config.ProjectConfig;
import com.zmj.sy.mom.srv.aps.feign.ApsWmsApiClient;
import com.zmj.sy.mom.srv.aps.feign.WmsLtkApiClient;
import com.zmj.sy.mom.srv.aps.feign.MbdFeign;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.*;
import com.zmj.sy.mom.srv.aps.utils.mybatisplus.WrapperUtil;
import feign.Request;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class ReportService {

    private final ApsWorkOrderMapper apsWorkOrderMapper;

    private final SinoCamPushDrawingMapper sinoCamPushDrawingMapper;

    private final SinoCamReceiveNestPartMapper sinoCamReceiveNestPartMapper;
    private final SinoCamReceiveNestExcessMapper sinoCamReceiveNestExcessMapper;
    private final SinoCamReceiveNestNestMapper sinoCamReceiveNestNestMapper;
    private final SinoCamReceiveNestPlateMapper sinoCamReceiveNestPlateMapper;
    private final SinoCamReceiveNestMoveMapper sinoCamReceiveNestMoveMapper;

    private final OrderBomMapper orderBomMapper;
    private final ApsWorkDetailMapper apsWorkDetailMapper;
    private final ImportMbdDxfMapper importMbdDxfMapper;
    private final OrderMapper orderMapper;
    private final ApsOrderMapper apsOrderMapper;
    private final WmsPlatePickMapper wmsPlatePickMapper;
    private final PlateMapper plateMapper;
    private final ProjectConfig projectConfig;
    private final PartPalletMapper partPalletMapper;
    private final WorkDetailTaskMapper workDetailTaskMapper;
    private final GroupMapper groupMapper;
    private final PartMapper partMapper;
    private final PlatePhaseMapper platePhaseMapper;
    private final WorkRecordMapper workRecordMapper;

    private final OrderPartMapper orderPartMapper;
    private final OrderAccessoriesMapper  orderAccessoriesMapper;
    private final ApsWmsApiClient apsWmsApiClient;
    private final JsonUtils jsonUtils;
    private final LogContentMapper logContentMapper;
    private final WmsLtkApiClient wmsLtkApiClient;
    private final MbdFeign mbdFeign;
    private final LantekNestPlateMapper lantekNestPlateMapper;
    private final LantekNestPartMapper lantekNestPartMapper;
    private final LantekPushPackageMapper lantekPushPackageMapper;
    private final LantekNestExcessMapper lantekNestExcessMapper;
    private final DictDataMapper dictDataMapper;

    @Value("${project.feign.dxf-download}")
    private String dxfDownload;

    @Value("${project.feign.ltk-png-url}")
    private String ltkPngUrl;

    public BasePageResVo<ReportProductionPartResVo> productionPart(ReportProductionPartReqVo reqVo) {

        QueryWrapper<ApsWorkOrder> query = Wrappers.query();
        query.eq(StringUtils.hasText(reqVo.getDrawing()), "ob.drawing", reqVo.getDrawing());
        query.eq(StringUtils.hasText(reqVo.getPlmId()), "ob.plm_id", reqVo.getPlmId());
        query.eq(StringUtils.hasText(reqVo.getSpec()), "ob.standards", reqVo.getSpec());

        query.eq("o.order_type", 1);
        query.ge("o.order_status", 6);
        query.ne("ob.work_chain", "WL");
        query.eq("ob.mater_type", "Platepart");
        Page<ReportProductionPartResVo> page = apsWorkOrderMapper.productionPart(query, reqVo.toPage());

        for (ReportProductionPartResVo e : page.getRecords()) {
            SinoCamReceiveNestPart one = sinoCamReceiveNestPartMapper.lambdaQuery()
                    .eq(SinoCamReceiveNestPart::getPartId, e.getPlmId())
                    .orderByDesc(SinoCamReceiveNestPart::getId)
                    .last(" limit 1 ")
                    .one();

            if (one != null) {
                e.setWidth(one.getWidth());
                e.setLength(one.getLength());
                e.setThickness(one.getThickness());
                e.setArea(one.getArea());
            }
        }

        return new BasePageResVo<>(page.getTotal(), page.getRecords());

    }

    /**
     * @Description: 添加查询条件
     * @author: hejiahui
     * @since: 2024/10/25 16:03
     */
    public BasePageResVo<ReportProductionPartResVo> productionPartPost(ReportProductionPartReqVo reqVo) {
        Map<String, String> compareType = reqVo.getQueryType();
        QueryWrapper<ApsWorkOrder> query = Wrappers.query();
        //添加查询条件
        if (StringUtils.hasText(reqVo.getPlmId())) {
            WrapperUtil.fixWrapper(query, "tsp.part_id", compareType.get("plmId"), reqVo.getPlmId());
        }
        if (StringUtils.hasText(reqVo.getSpec())) {
            WrapperUtil.fixWrapper(query, "tsp.texture", compareType.get("spec"), reqVo.getSpec());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getWidth())) {
            WrapperUtil.fixWrapper(query, "np.width", compareType.get("width"), reqVo.getWidth());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getLength())) {
            WrapperUtil.fixWrapper(query, "np.length", compareType.get("length"), reqVo.getLength());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getThickness())) {
            WrapperUtil.fixWrapper(query, "np.thickness", compareType.get("thickness"), reqVo.getThickness());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getStartDate())) {
            WrapperUtil.fixWrapper(query, "tsp.create_date_time", compareType.get("startDate"), reqVo.getStartDate());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getEndDate())) {
            WrapperUtil.fixWrapper(query, "tsp.modify_date_time", compareType.get("endDate"), reqVo.getEndDate());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getArea())) {
            WrapperUtil.fixWrapper(query, "np.area", compareType.get("area"), reqVo.getArea());
        }

        Page<ReportProductionPartResVo> page = apsWorkOrderMapper.productionPartPost(query, reqVo.toPage());
        if (page.getRecords().isEmpty()) {
            return BasePageResVo.empty(page.getTotal());
        }

        List<ImportMbdDxf> list = importMbdDxfMapper.lambdaQuery()
                .in(ImportMbdDxf::getPlmid, page.getRecords().stream().map(e -> e.getPlmId().endsWith("_170") ? e.getPlmId().substring(0, e.getPlmId().length() - 4) : e.getPlmId()).collect(Collectors.toList()))
                .list();
        Map<String, ImportMbdDxf> map = list.stream().collect(Collectors.toMap(ImportMbdDxf::getPlmid, Function.identity()));

        LambdaQueryWrapper<SinoCamReceiveNestPart> query11 = Wrappers.lambdaQuery();
        List<SinoCamReceiveNestPart> l = sinoCamReceiveNestPartMapper.maxRectangleArea(query11);
        Map<String, SinoCamReceiveNestPart> map1 = l.stream().collect(Collectors.toMap(SinoCamReceiveNestPart::getPartId, Function.identity(), (e1, e2)->{
            e1.setQuantity(e1.getQuantity() + e2.getQuantity());
            return e1;
        }));

        for (ReportProductionPartResVo record : page.getRecords()) {
            String plmId = record.getPlmId().endsWith("_170") ? record.getPlmId().substring(0, record.getPlmId().length() - 4) : record.getPlmId();
            ImportMbdDxf importMbdDxf = map.get(plmId);

            if (importMbdDxf != null) {
                record.setCreateDateTime(importMbdDxf.getCreateDateTime());
                record.setModifyDateTime(importMbdDxf.getModifyDateTime());
                if (StringUtils.hasText(importMbdDxf.getCreateNum())) {
                    record.setCreateUsername(importMbdDxf.getCreateNum() + "-" + importMbdDxf.getCreateName());
                }
                if (StringUtils.hasText(importMbdDxf.getModifyNum())) {
                    record.setModifyUsername(importMbdDxf.getModifyNum() + "-" + importMbdDxf.getModifyName());
                }
            }

            SinoCamReceiveNestPart sinoCamReceiveNestPart = map1.get(record.getPlmId());
            if (sinoCamReceiveNestPart != null) {
                record.setRectangleArea(sinoCamReceiveNestPart.getRectangleArea());
                if (record.getRectangleArea() != null) {
                    record.setRectangleArea(record.getRectangleArea().setScale(2, RoundingMode.HALF_UP));
                }
            }

            if (StringUtils.hasText(record.getPngUrl())) {
                record.setPngUrl(String.format(projectConfig.getUrlPre(), record.getPlmId() + ".png", record.getPngUrl()));
            }

        }

        return new BasePageResVo<>(page.getTotal(), page.getRecords());
    }


    public BasePageResVo<ReportProductionOrderResVo> productionOrder(ReportProductionOrderReqVo reqVo) {

        QueryWrapper<ApsWorkOrder> query = Wrappers.query();

        query.eq(StringUtils.hasText(reqVo.getDrawing()), "ob.drawing", reqVo.getDrawing());
        query.eq(StringUtils.hasText(reqVo.getPlmId()), "ob.plm_id", reqVo.getPlmId());
        query.eq(StringUtils.hasText(reqVo.getSpec()), "ob.standards", reqVo.getSpec());

        query.eq("o.order_type", 1);
        query.ge("o.order_status", 6);
        query.ne("ob.work_chain", "WL");
        query.orderByDesc(" awo.id");

        Page<ReportProductionOrderResVo> page = apsWorkOrderMapper.productionOrder(query, reqVo.toPage());

        for (ReportProductionOrderResVo e : page.getRecords()) {

            e.setNestCount(new BigDecimal(0));

            QueryWrapper<SinoCamReceiveNestPart> wrapper = Wrappers.query();
            wrapper.eq("awd.aps_work_order_id", e.getId());
            List<SinoCamReceiveNestPart> list = sinoCamReceiveNestPartMapper.findByWorkOrderId(wrapper);

            if (CollUtil.isNotEmpty(list)) {
                e.setWidth(list.get(0).getWidth());
                e.setLength(list.get(0).getLength());
                e.setThickness(list.get(0).getThickness());
                e.setHeight(list.get(0).getNetWeight());
                e.setNestCount(new BigDecimal(list.stream().map(SinoCamReceiveNestPart::getQuantity).reduce(0, Integer::sum)));
            }
            e.setRemainingCount(e.getOrderCount().subtract(e.getNestCount()));

        }

        return new BasePageResVo<>(page.getTotal(), page.getRecords());
    }

    /**
     * @Description: 套料报表-订单列表(添加新查询条件)
     * @author: hejiahui
     * @since: 2024/10/26 15:58
     */
    public BasePageResVo<ReportProductionOrderResVo> productionOrderPost(ReportProductionOrderReqVo reqVo) {

        QueryWrapper<ApsWorkOrder> query = Wrappers.query();
        Map<String, String> compareType = reqVo.getCompareType();
        //添加查询条件
        WrapperUtil.fixWrapper(query, StringUtils.hasText(reqVo.getSerialCode()), "o.serial_code", compareType.get("serialCode"), reqVo.getSerialCode());
        WrapperUtil.fixWrapper(query, StringUtils.hasText(reqVo.getCustomerName()), "o.customer_name", compareType.get("customerName"), reqVo.getCustomerName());
        WrapperUtil.fixWrapper(query, StringUtils.hasText(reqVo.getPkgCode()), "spp.processing_no", compareType.get("pkgCode"), reqVo.getPkgCode());
        WrapperUtil.fixWrapper(query, StringUtils.hasText(reqVo.getPlmId()), "spp.part_id", compareType.get("plmId"), reqVo.getPlmId());
        WrapperUtil.fixWrapper(query, StringUtils.hasText(reqVo.getMaterName()), "spp.part_name", compareType.get("materName"), reqVo.getMaterName());
        WrapperUtil.fixWrapper(query, StringUtils.hasText(reqVo.getSpec()), "spd.texture", compareType.get("spec"), reqVo.getSpec());
        WrapperUtil.fixWrapper(query, ObjectUtils.isNotEmpty(reqVo.getThickness()), "spd.thick_ness", compareType.get("thickness"), reqVo.getThickness());
        WrapperUtil.fixWrapper(query, ObjectUtils.isNotEmpty(reqVo.getLength()), "op.length", compareType.get("length"), reqVo.getLength());
        WrapperUtil.fixWrapper(query, ObjectUtils.isNotEmpty(reqVo.getWidth()), "op.width", compareType.get("width"), reqVo.getWidth());
        WrapperUtil.fixWrapper(query, ObjectUtils.isNotEmpty(reqVo.getOrderCount()), "spp.plan_amount", compareType.get("orderCount"), reqVo.getOrderCount());
        WrapperUtil.fixWrapper(query, ObjectUtils.isNotEmpty(reqVo.getNestCount()), "spp.plan_finish_amount", compareType.get("nestCount"), reqVo.getNestCount());
        WrapperUtil.fixWrapper(query, ObjectUtils.isNotEmpty(reqVo.getParentMaterCode()), "spp.component_id", compareType.get("parentMaterCode"), reqVo.getParentMaterCode());
        WrapperUtil.fixWrapper(query, ObjectUtils.isNotEmpty(reqVo.getProductCode()), "spp.product_id", compareType.get("productCode"), reqVo.getParentMaterCode());
        WrapperUtil.fixWrapper(query, ObjectUtils.isNotEmpty(reqVo.getGroupCode()), "awd.group_code", compareType.get("groupCode"), reqVo.getGroupCode());

        if (reqVo.getDrawingReady() != null) {
            if (reqVo.getDrawingReady().equals(1)) {
                query.isNull("awd.drawing_path");
            } else if (reqVo.getDrawingReady().equals(2)) {
                query.isNotNull("awd.drawing_path");
            } else {
                throw SyExceptionUtils.e("未知的绘图状态");
            }
        }

        query.in("o.order_type", 1, 4);
        if (StringUtils.hasText(reqVo.getSort())) {
            reqVo.setSort(reqVo.getSort().replace("planStartDateTime", "spp.need_date"));
            reqVo.setSort(reqVo.getSort().replace("planEndDateTime", "spp.need_date"));
            if (StringUtils.hasText(reqVo.getOrder()) && reqVo.getOrder().trim().equals("desc")) {
                query.orderByDesc(reqVo.getSort());
            } else {
                query.orderByAsc(reqVo.getSort());
            }
        }
        if (StringUtils.hasText(reqVo.getPushType())) {
            query.eq("spp.push_type", reqVo.getPushType());
        }

        if (reqVo.getNestStatus() != null) {
            if (reqVo.getNestStatus() == 0) {
                // 未完成
                query.apply(" spp.plan_amount > spp.plan_finish_amount ");
            } else if (reqVo.getNestStatus() == 1) {
                // 已完成
                query.apply(" spp.plan_amount <= spp.plan_finish_amount ");
            } else {
                throw SyExceptionUtils.e("未知的完成状态：{}", reqVo.getNestStatus());
            }
        }

        query.eq("spp.deleted", 0);
        query.eq("spd.deleted", 0);
        query.eq("awd.deleted", 0);
        query.eq("op.deleted", 0);
        query.eq("o.deleted", 0);

        Page<ReportProductionOrderResVo> page = apsWorkOrderMapper.productionOrderPost(query, reqVo.toPage());
        for (ReportProductionOrderResVo record : page.getRecords()) {
            record.setRemainingCount(record.getOrderCount().subtract(record.getNestCount()));
            record.setNestStatus(record.getOrderCount().compareTo(record.getNestCount()) > 0 ? 0 : 1);
            if (StringUtils.hasText(record.getFilePath())) {
                record.setDrawingReady(2);
            } else {
                record.setDrawingReady(1);
            }

            LocalDateTime planStartDateTime = record.getPlanStartDateTime();
            record.setPlanStartDateTime(planStartDateTime.minusHours(13));
            record.setPlanEndDateTime(planStartDateTime.minusHours(11));
            if (StringUtils.hasText(record.getPngUrl())) {
                record.setPngUrl(String.format(projectConfig.getUrlPre(), record.getPlmId() + ".png", record.getPngUrl()));
            }
        }
        return new BasePageResVo<>(page.getTotal(), page.getRecords());
    }

    public BasePageResVo<ReportProductionNestResVo> productionNest(ReportProductionNestReqVo reqVo) {
        QueryWrapper<SinoCamReceiveNestPlate> query = Wrappers.query();
        query.eq(StringUtils.hasText(reqVo.getNestId()), "nest.nest_id", reqVo.getNestId());
        Page<ReportProductionNestResVo> reportProductionNestResVoPage = sinoCamReceiveNestPlateMapper.productionNest(query, reqVo.toPage());
        for (ReportProductionNestResVo record : reportProductionNestResVoPage.getRecords()) {
//            record.setTotal(1);
            record.setStatus(1);
            if (record.getCutTime() != null) {
                record.setCutTime(record.getCutTime().divide(new BigDecimal(60), 1, RoundingMode.HALF_UP));
            }
        }
        return new BasePageResVo<>(reportProductionNestResVoPage.getTotal(), reportProductionNestResVoPage.getRecords());
    }

    /**
     * @Description: 套料报表-套料列表(添加新查询条件)
     * @author: hejiahui
     * @since: 2024/10/28 10:57
     */
    public BasePageResVo<ReportProductionNestResVo> productionNestPost(ReportProductionNestReqVo reqVo) {
        QueryWrapper<SinoCamReceiveNestPlate> query = Wrappers.query();
        Map<String, String> compareType = reqVo.getCompareType();
        //添加查询条件
        if (StringUtils.hasText(reqVo.getPlateCode())) {
            WrapperUtil.fixWrapper(query, "plate.stock_list_no", "like", reqVo.getPlateCode());
        }
        if (StringUtils.hasText(reqVo.getHeatCode())) {
            WrapperUtil.fixWrapper(query, "plate.heat_number", "like", reqVo.getHeatCode());
        }
        if (StringUtils.hasText(reqVo.getNestId())) {
            WrapperUtil.fixWrapper(query, "nest.nest_id", "like", reqVo.getNestId());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getRate())) {
            WrapperUtil.fixWrapper(query, "plate.rate", compareType.get("rate"), reqVo.getRate());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getCutTime())) {
            WrapperUtil.fixWrapper(query, " move1.move_time + move2.move_time", compareType.get("cutTime"), reqVo.getCutTime());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getGroupCode())) {
            WrapperUtil.fixWrapper(query, "nest.option_id", "like", reqVo.getGroupCode());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getWidth())) {
            WrapperUtil.fixWrapper(query, "plate.width", compareType.get("width"), reqVo.getWidth());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getLength())) {
            WrapperUtil.fixWrapper(query, "plate.length", compareType.get("length"), reqVo.getLength());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getSideLength())) {
            WrapperUtil.fixWrapper(query, "plate.side_length", compareType.get("sideLength"), reqVo.getSideLength());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getCutLength())) {
            WrapperUtil.fixWrapper(query, "move1.cut_length", compareType.get("cutLength"), reqVo.getCutLength());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getEmptyLength())) {
            WrapperUtil.fixWrapper(query, "move2.cut_length", compareType.get("emptyLength"), reqVo.getEmptyLength());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getPickStatus())) {
            WrapperUtil.fixWrapper(query, "pick.plate_state", compareType.get("pickStatus"), reqVo.getPickStatus());
        }
        if (StringUtils.hasText(reqVo.getPushType())) {
            if ("1".equals(reqVo.getPushType())) {
                query.isNull("nest.lantek_code");
            } else if ("2".equals(reqVo.getPushType())) {
                query.isNotNull("nest.lantek_code");
            }
        }

        query.like(StringUtils.hasText(reqVo.getTexture()), "plate.texture", reqVo.getTexture());
        query.eq(reqVo.getThickness() != null, "plate.norm", reqVo.getThickness());

        query.isNotNull("pick.plate_state");
        query.orderByDesc("plate.id");
//        query.orderByAsc(StringUtils.hasText(reqVo.getSort()), "xxx",reqVo.getSort());
        Page<ReportProductionNestResVo> reportProductionNestResVoPage = sinoCamReceiveNestPlateMapper.productionNest(query, reqVo.toPage());
        for (ReportProductionNestResVo record : reportProductionNestResVoPage.getRecords()) {
//            record.setTotal(1);
            record.setStatus(1);
            if (record.getCutTime() != null) {
                record.setCutTime(record.getCutTime().divide(new BigDecimal(60), 2, RoundingMode.HALF_UP));
            }

            record.setCutWeight(record.getCutWeight().setScale(2, RoundingMode.HALF_UP));
            if (record.getCutLength() != null) {
                record.setSideRate(record.getSideLength().divide(record.getCutLength(), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
            } else {
                record.setSideRate(BigDecimal.ZERO);
            }

            if (StringUtils.hasText(record.getPngUrl())) {
                record.setPngUrl(String.format(projectConfig.getUrlPre(), record.getPlateCode() + ".png", record.getPngUrl()));
            }
            record.setPushType(StringUtils.hasText(record.getPushType()) ? "2" : "1");
        }
        return new BasePageResVo<>(reportProductionNestResVoPage.getTotal(), reportProductionNestResVoPage.getRecords());
    }

    public BasePageResVo<ReportProductionNestPartResVo> productionNestPart(BaseIdReqVo reqVo) {

        SinoCamReceiveNestPlate plate = sinoCamReceiveNestPlateMapper.selectById(reqVo.getId());
        QueryWrapper<SinoCamReceiveNestPart> query = Wrappers.query();
        query.eq("part.plate_code", plate.getStockListNo());
        List<ReportProductionNestPartResVo> list = sinoCamReceiveNestPartMapper.productionNestPart(query);
        for (ReportProductionNestPartResVo r : list) {
            if (r == null || r.getPlmId() == null) {
                r.setPlmId("异常零件");
                continue;
            }
            ImportMbdDxf mbdDxf = importMbdDxfMapper.lambdaQuery().eq(ImportMbdDxf::getPlmid, r.getPlmId().replace("_170", "")).one();
            if (mbdDxf != null) {
                r.setDxfPath(dxfDownload + mbdDxf.getPath());
                r.setCreateUserCode(mbdDxf.getCreateNum() + "-" + mbdDxf.getCreateName());
                r.setCreateDateTime(mbdDxf.getCreateDateTime());
                r.setModifyUserCode(mbdDxf.getModifyNum() + "-" + mbdDxf.getModifyName());
                r.setModifyDateTime(mbdDxf.getModifyDateTime());
            }
            if (StringUtils.hasText(r.getPkgCode())) {
                r.setPkgCode(PkgUtils.gen(Integer.parseInt(r.getPkgCode())));
            }
        }

        return new BasePageResVo<>(list.size(), list);
    }

    public BasePageResVo<ReportProductionNestPlateResVo> productionNestPlate(BaseIdReqVo reqVo) {
        QueryWrapper<SinoCamReceiveNestPlate> query = Wrappers.query();
        query.eq("plate.id", reqVo.getId());
        List<ReportProductionNestPlateResVo> list = sinoCamReceiveNestPlateMapper.productionNestPlate(query);
        for (ReportProductionNestPlateResVo a : list) {
            a.setLength(a.getLength().setScale(2, RoundingMode.HALF_UP));
            a.setWidth(a.getWidth().setScale(2, RoundingMode.HALF_UP));
        }
        return new BasePageResVo<>(list.size(), list);
    }

    public BasePageResVo<ReportProductionNestStatResVo> productionNestStat(BaseIdReqVo reqVo) {

        SinoCamReceiveNestPlate plate = sinoCamReceiveNestPlateMapper.selectById(reqVo.getId());

        List<SinoCamReceiveNestMove> data = sinoCamReceiveNestMoveMapper.lambdaQuery()
                .eq(SinoCamReceiveNestMove::getReceiveNestId, plate.getReceiveNestId())
                .list();

        List<ReportProductionNestStatResVo> collect = data.stream()
                .map(e -> {
                    ReportProductionNestStatResVo vo = new ReportProductionNestStatResVo();
                    vo.setMoveType(e.getMoveType());
                    vo.setCutLength(e.getCutLength().divide(new BigDecimal(1000)).setScale(2, RoundingMode.HALF_UP));
                    vo.setCutTime((new BigDecimal(e.getMoveTime()).add(new BigDecimal(e.getTotalHoleTime()))).divide(new BigDecimal(60), 2, RoundingMode.HALF_UP));
                    return vo;
                })
                .collect(Collectors.toList());


        return new BasePageResVo<>(collect.size(), collect);
    }

    public BasePageResVo<ReportProductionPartOrderResVo> productionPartOrder(ReportProductionPartOrderReqVo reqVo) {

        QueryWrapper<ApsWorkOrder> query = Wrappers.query();

        query.like(StringUtils.hasText(reqVo.getSerialCode()), "o.serial_code", reqVo.getSerialCode());

        if (StringUtils.hasText(reqVo.getPkgCode())) {
            try {
                int i = PkgUtils.rollBack(reqVo.getPkgCode());
                query.eq("ao.seq", i);
            } catch (NumberFormatException e) {
                throw SyExceptionUtils.e("批次格式错误");
            }
        }

        query.like(StringUtils.hasText(reqVo.getTexture()), "pd.texture", reqVo.getTexture());
        query.like(reqVo.getThickness() != null, "pd.thick_ness", reqVo.getThickness());
        if (reqVo.getDrawStatus() != null) {
            query.eq("part.draw_status", reqVo.getDrawStatus());
        }

        query.in("o.order_type", 1, 4);
        query.ge("o.order_status", 6);
        query.eq("awo.mater_type", "Platepart");
        query.eq("awo.plm_id", reqVo.getPlmId());

        Page<ReportProductionPartOrderResVo> orderList = orderBomMapper.productionPartOrder(query, reqVo.toPage());

        if (CollUtil.isEmpty(orderList.getRecords())) {
            return new BasePageResVo<>(orderList.getTotal(), orderList.getRecords());
        }


        for (ReportProductionPartOrderResVo r : orderList.getRecords()) {
            r.setRemainingCount(r.getOrderCount().subtract(new BigDecimal(r.getNestCount())));
            r.setPkgCode(PkgUtils.gen(r.getSeq()));
            if (r.getDrawStatus() > 2) {
                r.setDrawStatus(2);
            }

            LocalDateTime planStartDateTime = r.getPlanStartDateTime();
            r.setPlanStartDateTime(planStartDateTime.minusHours(13));
            r.setPlanEndDateTime(planStartDateTime.minusHours(11));
        }

        return new BasePageResVo<>(orderList.getTotal(), orderList.getRecords());
    }


    /**
     * 套料报表-零件列表-关联订单(添加新查询条件)
     *
     * @param reqVo
     * @return "id": 3236,
     * "serialCode": "0001-Z24-017Z",
     * "pkgCode": "WP-01",
     * "spec": null,
     * "orderId": 2,
     * "workOrderId": 3236,
     * "length": null,
     * "width": null,
     * "thickness": null,
     * "area": null,
     * "weight": null,
     * "planStartDateTime": null,
     * "drawing": null,
     * "plmId": "0178-08-0101B-02_170",
     * "orderCount": 20.00,
     * "remainingCount": 0.00,
     * "nestCount": 20,
     * "errorCount": 0,
     * "status": 1,
     * "statusRemark": null,
     * "apsWorkDetailId": 19690
     */
    public BasePageResVo<ReportProductionPartOrderResVo> productionPartOrderPost(BasePlmIdPageReqVo reqVo) {
//        Map<String, String> compareType = reqVo.getCompareType();
        // 获取需要切割的工序
        List<String> phaseCodeList = projectConfig.getCuttingProcess();

        QueryWrapper<ApsWorkOrder> query = Wrappers.query();

        //添加查询条件
        if (StringUtils.hasText(reqVo.getSerialCode())) {
//            WrapperUtil.fixWrapper(query, "o.serial_code", compareType.get("serialCode"), reqVo.getSerialCode());
        }
//        if (StringUtils.hasText(reqVo.getPkgCode())) {
//            WrapperUtil.fixWrapper(query, "ao.seq", compareType.get("pkgCode"), reqVo.getPkgCode());
//        }
//        if (reqVo.getOrderId() != null) {
//            WrapperUtil.fixWrapper(query, "o.id", compareType.get("orderId"), reqVo.getOrderId());
//        }
//        if (reqVo.getWorkOrderId() != null) {
//            WrapperUtil.fixWrapper(query, "awo.id", compareType.get("workOrderId"), reqVo.getWorkOrderId());
//        }
//        if (StringUtils.hasText(reqVo.getPlmId())) {
//            WrapperUtil.fixWrapper(query, "awo.plm_id", compareType.get("plmId"), reqVo.getPlmId());
//        }

        query.eq("o.order_type", 1);
        query.ge("o.order_status", 6);
        query.ne("awo.work_chain", "WL");
        query.eq("awo.plm_id", reqVo.getPlmId());
        query.in("awd.phase_code", phaseCodeList);
        Page<ReportProductionPartOrderResVo> orderList = orderBomMapper.productionPartOrder(query, reqVo.toPage());

        if (CollUtil.isEmpty(orderList.getRecords())) {
            return new BasePageResVo<>(orderList.getTotal(), orderList.getRecords());
        }

//        where awo.mater_type = 'Platepart'  and o.order_type in (1, 3, 4);
        for (ReportProductionPartOrderResVo r : orderList.getRecords()) {
            Long total = sinoCamReceiveNestPartMapper.selectTotalCountById(r.getId());
            if (total == null) {
                total = 0L;
            }
            r.setNestCount(total.intValue());
            r.setRemainingCount(r.getOrderCount().subtract(new BigDecimal(r.getNestCount())));
            r.setPkgCode(PkgUtils.gen(Integer.parseInt(r.getPkgCode())));
        }


        return new BasePageResVo<>(orderList.getTotal(), orderList.getRecords());
    }

    public BasePageResVo<ReportProductionPartNestResVo> productionPartNest(ReportProductionPartNestReqVo reqVo) {
        QueryWrapper<SinoCamReceiveNestPart> query = Wrappers.query();

        query.like(StringUtils.hasText(reqVo.getNestId()), "nest.nest_id", reqVo.getNestId());
        query.like(StringUtils.hasText(reqVo.getGroupCode()), "nest.option_id", reqVo.getGroupCode());
        query.eq(reqVo.getLength() != null, "part.length", reqVo.getLength());
        query.eq(reqVo.getWidth() != null, "part.width", reqVo.getWidth());
        query.eq(reqVo.getThickness() != null, "part.thickness", reqVo.getThickness());

        query.eq("part.part_id", reqVo.getPlmId());
        query.eq("nest.version_brief", "V2");
        Page<ReportProductionPartNestResVo> page = sinoCamReceiveNestPartMapper.productionPartNest(query, reqVo.toPage());
        for (ReportProductionPartNestResVo record : page.getRecords()) {
            record.setRulerPlate("2500 * 10000");
            record.setModifyUserCode(record.getCreateUserCode());
            record.setModifyDateTime(record.getCreateDateTime());
        }
        return new BasePageResVo<>(page.getTotal(), page.getRecords());
    }


    /**
     * 套料报表-零件列表-关联套料(添加新查询条件)
     *
     * @param reqVo
     * @return
     */
    public BasePageResVo<ReportProductionPartNestResVo> productionPartNestPost(BasePlmIdPageReqVo reqVo) {
//        Map<String, String> compareType = reqVo.getCompareType();
        QueryWrapper<SinoCamReceiveNestPart> query = Wrappers.query();
//        //添加查询条件
//        if (StringUtils.hasText(reqVo.getNestId())) {
//            WrapperUtil.fixWrapper(query, "nest.nest_id", compareType.get("nestId"), reqVo.getNestId());
//        }
//
//        if (StringUtils.hasText(reqVo.getGroupCode())) {
//            WrapperUtil.fixWrapper(query, "nest.option_id", compareType.get("groupCode"), reqVo.getGroupCode());
//        }
//
//        if (reqVo.getPlanStartTime() != null) {
//            WrapperUtil.fixWrapper(query, "nest.need_date", compareType.get("planStartTime"), reqVo.getPlanStartTime());
//        }
//
//        if (reqVo.getOrderCount() != null) {
//            WrapperUtil.fixWrapper(query, "part.quantity", compareType.get("orderCount"), reqVo.getOrderCount());
//        }


//        query.eq("o.order_type", 1);
//        query.ge("o.order_status", 6);
        query.eq("part.part_id", reqVo.getPlmId());
        Page<ReportProductionPartNestResVo> page = sinoCamReceiveNestPartMapper.productionPartNest(query, reqVo.toPage());
        return new BasePageResVo<>(page.getTotal(), page.getRecords());
    }

    public BasePageResVo<ReportProductionOrderPartResVo> productionOrderPart(ReportProductionOrderPartReqVo reqVo) {
        // 查出这个零件详情

        ApsWorkOrder apsWorkOrder = apsWorkOrderMapper.selectById(reqVo.getId());

        ReportProductionOrderPartResVo r = new ReportProductionOrderPartResVo();
        r.setPlmId(apsWorkOrder.getPlmId());
        r.setSpec(apsWorkOrder.getStandards());
        r.setMaterCode(apsWorkOrder.getMaterCode());
        r.setPlanStartDateTime(apsWorkOrder.getPlanStartDateTime());

        String code = r.getPlmId();
        if (code.endsWith("_170")) {
            code = code.substring(0, r.getPlmId().indexOf("_170"));
        }
        ImportMbdDxf mbdDxf = importMbdDxfMapper.lambdaQuery().eq(ImportMbdDxf::getPlmid, code).one();

        if (mbdDxf != null) {
            r.setDxfPath(dxfDownload + mbdDxf.getPath());
            r.setDrawVersion(mbdDxf.getDocVersion());
            r.setCreateUserCode(mbdDxf.getCreateNum() + "-" + mbdDxf.getCreateName());
            r.setCreateDateTime(mbdDxf.getCreateDateTime());
            r.setModifyUserCode(mbdDxf.getModifyNum() + "-" + mbdDxf.getModifyName());
            r.setModifyDateTime(mbdDxf.getModifyDateTime());
        }

/*        SinoCamPushDrawing one = sinoCamPushDrawingMapper.lambdaQuery().eq(SinoCamPushDrawing::getPartId, r.getPlmId()).eq(SinoCamPushDrawing::getOrderId, apsWorkOrder.getOrderId()).one();
        if (one != null) {
            r.setCreateUserCode(one.getCreateUsername());
            r.setCreateDateTime(one.getCreateDateTime());
            r.setModifyUserCode(one.getModifyUsername());
            r.setModifyDateTime(one.getModifyDateTime());
        }*/

        QueryWrapper<SinoCamReceiveNestPart> wrapper = Wrappers.query();
        wrapper.eq("awd.id", reqVo.getId());
        wrapper.last(" limit 1");
        List<SinoCamReceiveNestPart> list = sinoCamReceiveNestPartMapper.findByWorkOrderId(wrapper);


        if (CollUtil.isNotEmpty(list)) {
            r.setWidth(list.get(0).getWidth());
            r.setLength(list.get(0).getLength());
            r.setThickness(list.get(0).getThickness());
            r.setNetWeight(list.get(0).getNetWeight());
            r.setArea(list.get(0).getArea());
        }

        return new BasePageResVo<>(1L, Lists.newArrayList(r));
    }

    public BasePageResVo<ReportProductionOrderNestResVo> productionOrderNest(ReportProductionOrderNestReqVo reqVo) {

        QueryWrapper<SinoCamReceiveNestPart> wrapper = Wrappers.query();
        wrapper.eq("awd.aps_work_order_id", reqVo.getId());
        List<SinoCamReceiveNestPart> list = sinoCamReceiveNestPartMapper.findByWorkOrderId(wrapper);

        if (CollUtil.isEmpty(list)) {
            return BasePageResVo.empty();
        }

        // 查出这个零件套了几次料,每次套料的详细信息
        QueryWrapper<SinoCamReceiveNestPart> query = Wrappers.query();
        query.in("part.nest_plan_id", list.stream().map(SinoCamReceiveNestPart::getNestPlanId).distinct().collect(Collectors.toList()));
        Page<ReportProductionOrderNestResVo> page = sinoCamReceiveNestPartMapper.productionOrderNest(query, reqVo.toPage());
        for (ReportProductionOrderNestResVo a : page.getRecords()) {
            a.setPngUrl(String.format(projectConfig.getUrlPre(), a.getPlateCode(), a.getPngUrl()));
        }
        return new BasePageResVo<>(page.getTotal(), page.getRecords());
    }

    public BaseListResVo<ReportProOrderTreeResVo> productionOrderTree(ReportProOrderTreeReqVo reqVo) {


        if (!StringUtils.hasText(reqVo.getId())) {
            ReportProOrderTreeResVo r1 = new ReportProOrderTreeResVo();
            r1.setTreeType(1);
            r1.setId("1$1");
            r1.setName("产品订单");
            r1.setLeaf(false);
            r1.setIconCls(8);

            ReportProOrderTreeResVo r2 = new ReportProOrderTreeResVo();
            r2.setTreeType(11);
            r2.setId("11$1");
            r2.setName("工装订单");
            r2.setLeaf(false);
            r2.setIconCls(9);

            ReportProOrderTreeResVo r3 = new ReportProOrderTreeResVo();
            r3.setTreeType(21);
            r3.setId("21$1");
            r3.setName("外揽订单");
            r3.setLeaf(false);
            r3.setIconCls(9);

//            ReportProOrderTreeResVo r3 = new ReportProOrderTreeResVo();
//            r3.setTreeType(20);
//            r3.setId("20$1");
//            r3.setName("物料订单");
//            r3.setLeaf(true);
//            r3.setIconCls(10);

            return new BaseListResVo<>(Lists.newArrayList(r1, r2, r3));
        }

        // 查询产品订单
        if (reqVo.getId().equals("1$1")) {
            LambdaQueryWrapper<Order> query = Wrappers.lambdaQuery();
            query.eq(Order::getOrderType, 1);
            if (Boolean.TRUE.equals(reqVo.getHistory())) {
                query.le(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            } else {
                query.gt(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            }
            query.ge(Order::getOrderStatus, 6);
            List<Order> orderList = orderMapper.selectList(query);

            // 2 施工号
            List<ReportProOrderTreeResVo> collect = orderList.stream()
                    .map(e -> {
                        ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
                        r.setStatus(e.getOrderStatus());
//                        if(r.getStatus().equals(10)){
//                            r.setStatus(9);
//                        }
                        r.setDeliveryDate(e.getDeliveryDateTime().toLocalDate());
                        r.setName(e.getSerialCode() + "-" + e.getMaterName());
                        r.setTreeType(2);
                        r.setId(r.getTreeType() + "$" + e.getId());
                        r.setPid("1$1");
                        if (e.getOrderStatus().equals(8)) {
                            r.setIconCls(2);
                        } else if (e.getOrderStatus().equals(9)|| e.getOrderStatus().equals(10)) {
                            r.setIconCls(1);
                        } else {
                            r.setIconCls(3);
                        }
                        r.setFinishCount(new BigDecimal(e.getFinishQty()));
                        r.setTotalCount(new BigDecimal(e.getOrderQty()));
                        r.setUnit("架");
                        return r;
                    })
                    .collect(Collectors.toList());
            return new BaseListResVo<>(collect);
        }

        // 查询订单下的所有包
        String[] split = reqVo.getId().split("\\$");
        if (split[0].equals("2")) {
            // 查出所有的子节点
            List<ApsOrder> apsOrderList = apsOrderMapper.lambdaQuery()
                    .eq(ApsOrder::getOrderId, Integer.parseInt(split[1]))
                    .list();

            List<ReportProOrderTreeResVo> collect = apsOrderList.stream()
                    .sorted(Comparator.comparingInt(ApsOrder::getSeq))
                    .map(e -> {
                        ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
                        r.setTreeType(3);
                        r.setId(r.getTreeType() + "$" + e.getId());
                        r.setName(PkgUtils.gen(e.getSeq()));
                        r.setPid(reqVo.getId());
                        r.setDeliveryDate(e.getPlanEndDateTime().toLocalDate());
                        r.setIconCls(4);
                        r.setFinishCount(new BigDecimal(e.getFinishQty()));
                        r.setTotalCount(new BigDecimal(e.getOrderQty()));
                        r.setUnit("架");
                        return r;
                    })
                    .collect(Collectors.toList());

            return new BaseListResVo<>(collect);
        }

        // 查询包下的所有节点
        if (split[0].equals("3")) {
            // 查出所有的子节点
            List<ApsWorkOrder> workOrderList = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getApsOrderId, Integer.parseInt(split[1]))
                    .isNull(ApsWorkOrder::getPid)
                    .list();

            List<ReportProOrderTreeResVo> collect = workOrderList.stream()
                    .map(e -> {
                        ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
                        r.setTreeType(4);
                        r.setId(r.getTreeType() + "$" + e.getId());
                        r.setName(e.getPlmId());
                        r.setPid(reqVo.getId());
                        r.setLeaf(false);
                        r.setDeliveryDate(e.getPlanEndDateTime().toLocalDate());
                        r.setIconCls(5);

                        r.setFinishCount(e.getFinishCount());
                        r.setTotalCount(e.getOrderCount());
                        r.setUnit("件");
                        return r;
                    })
                    .collect(Collectors.toList());

            return new BaseListResVo<>(collect);
        }

        // 查询包下的所有节点
        if (split[0].equals("4")) {
            // 查出所有的子节点
            List<ApsWorkOrder> workOrderList = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getPid, Integer.parseInt(split[1]))
                    .list();

            if (CollUtil.isEmpty(workOrderList)) {
                return BaseListResVo.empty();
            }

            List<Integer> idList = workOrderList.stream().map(BaseEntity::getId).collect(Collectors.toList());
            List<ApsWorkOrder> parentList = apsWorkOrderMapper.lambdaQuery().in(ApsWorkOrder::getPid, idList).list();
            Map<Integer, List<ApsWorkOrder>> map = parentList.stream().collect(Collectors.groupingBy(ApsWorkOrder::getPid));

            List<String> plmIdList = workOrderList.stream().map(ApsWorkOrder::getPlmId).distinct().collect(Collectors.toList());
            Optional<Integer> first = workOrderList.stream().map(ApsWorkOrder::getOrderId).distinct().findFirst();
            Order order = orderMapper.selectById(first.get());

            List<Part> list = partMapper.lambdaQuery().in(Part::getPlmId, plmIdList).eq(Part::getPhaseCode, WorkshopProp.KJ_PHASE_CODE).eq(Part::getConstructNo, order.getConstructNo()).list();
            Map<String, Part> partMap = list.stream().collect(Collectors.toMap(Part::getPlmId, Function.identity()));

            List<ReportProOrderTreeResVo> collect = workOrderList.stream()
                    .sorted(Comparator.comparing(ApsWorkOrder::getMaterType).thenComparing(ApsWorkOrder::getPlmId).reversed())
                    .map(e -> {
                        ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
                        r.setTreeType(4);
                        r.setId(r.getTreeType() + "$" + e.getId());
                        r.setName(e.getPlmId());
                        r.setPid(reqVo.getId());
                        r.setLeaf(map.get(e.getId()) == null);
                        r.setDeliveryDate(e.getPlanEndDateTime().toLocalDate());
                        if (e.getWorkChain().equals("WL")) {
                            r.setIconCls(7);
                        } else {
                            if (e.getMaterType().equals("Assembly")) {
                                r.setIconCls(5);
                            } else if (e.getMaterType().equals("Platepart")){
                                r.setIconCls(6);
                            } else {
                                r.setIconCls(7);
                            }
                        }

                        Part part = partMap.get(e.getPlmId());
                        if (part == null) {
                            r.setInProgressCount(new BigDecimal(0));
                        } else {
                            r.setInProgressCount(new BigDecimal(part.getPartCount()));
                        }

                        r.setFinishCount(e.getFinishCount());
                        r.setTotalCount(e.getOrderCount());
                        r.setUnit("件");
                        return r;
                    })
                    .collect(Collectors.toList());

            return new BaseListResVo<>(collect);
        }

        if (split[0].equals("11")) {
            LambdaQueryWrapper<Order> query = Wrappers.lambdaQuery();
            query.in(Order::getOrderType, 4);
            if (Boolean.TRUE.equals(reqVo.getHistory())) {
                query.le(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            } else {
                query.gt(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            }
            query.ge(Order::getOrderStatus, 6);
            List<Order> orderList = orderMapper.selectList(query);

            // 2 施工号
            List<ReportProOrderTreeResVo> collect = orderList.stream()
                    .map(e -> {
                        ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
                        r.setStatus(e.getOrderStatus());
                        if(r.getStatus().equals(10)){
                            r.setStatus(9);
                        }
                        r.setDeliveryDate(e.getDeliveryDateTime().toLocalDate());
                        r.setName(e.getSerialCode() + "-" + e.getMaterName());
                        r.setTreeType(2);
                        r.setId(r.getTreeType() + "$" + e.getId());
                        r.setPid("10$1");
                        if (e.getOrderStatus().equals(8)) {
                            r.setIconCls(2);
                        } else if (e.getOrderStatus().equals(9)) {
                            r.setIconCls(1);
                        } else {
                            r.setIconCls(3);
                        }
                        r.setFinishCount(new BigDecimal(e.getFinishQty()));
                        r.setTotalCount(new BigDecimal(e.getOrderQty()));
                        r.setUnit("架");
                        return r;
                    })
                    .collect(Collectors.toList());
            return new BaseListResVo<>(collect);
        }

//        if (split[0].equals("12")) {
//            // 查出所有的子节点
//            List<ApsOrder> apsOrderList = apsOrderMapper.lambdaQuery()
//                    .eq(ApsOrder::getOrderId, Integer.parseInt(split[1]))
//                    .list();
//
//            List<ReportProOrderTreeResVo> collect = apsOrderList.stream()
//                    .sorted(Comparator.comparingInt(ApsOrder::getSeq))
//                    .map(e -> {
//                        ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
//                        r.setTreeType(3);
//                        r.setId(r.getTreeType() + "$" + e.getId());
//                        r.setName(PkgUtils.gen(e.getSeq()));
//                        r.setPid(reqVo.getId());
//                        r.setDeliveryDate(e.getPlanEndDateTime().toLocalDate());
//                        r.setIconCls(4);
//                        r.setFinishCount(new BigDecimal(e.getFinishQty()));
//                        r.setTotalCount(new BigDecimal(e.getOrderQty()));
//                        r.setUnit("架");
//                        return r;
//                    })
//                    .collect(Collectors.toList());
//
//            return new BaseListResVo<>(collect);
//        }

        if (split[0].equals("21")) {
            LambdaQueryWrapper<Order> query = Wrappers.lambdaQuery();
            query.in(Order::getOrderType, 3);
            if (Boolean.TRUE.equals(reqVo.getHistory())) {
                query.le(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            } else {
                query.gt(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            }
            query.ge(Order::getOrderStatus, 6);
            List<Order> orderList = orderMapper.selectList(query);

            // 2 施工号
            List<ReportProOrderTreeResVo> collect = orderList.stream()
                    .map(e -> {
                        ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
                        r.setStatus(e.getOrderStatus());
                        if(r.getStatus().equals(10)){
                            r.setStatus(9);
                        }
                        r.setDeliveryDate(e.getDeliveryDateTime().toLocalDate());
                        r.setName(e.getSerialCode() + "-" + e.getMaterName());
                        r.setTreeType(2);
                        r.setId(r.getTreeType() + "$" + e.getId());
                        r.setPid("20$1");
                        if (e.getOrderStatus().equals(8)) {
                            r.setIconCls(2);
                        } else if (e.getOrderStatus().equals(9)) {
                            r.setIconCls(1);
                        } else {
                            r.setIconCls(3);
                        }
                        r.setFinishCount(new BigDecimal(e.getFinishQty()));
                        r.setTotalCount(new BigDecimal(e.getOrderQty()));
                        r.setUnit("架");
                        return r;
                    })
                    .collect(Collectors.toList());
            return new BaseListResVo<>(collect);
        }

//        if (split[0].equals("22")) {
//            // 查出所有的子节点
//            List<ApsOrder> apsOrderList = apsOrderMapper.lambdaQuery()
//                    .eq(ApsOrder::getOrderId, Integer.parseInt(split[1]))
//                    .list();
//
//            List<ReportProOrderTreeResVo> collect = apsOrderList.stream()
//                    .sorted(Comparator.comparingInt(ApsOrder::getSeq))
//                    .map(e -> {
//                        ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
//                        r.setTreeType(3);
//                        r.setId(r.getTreeType() + "$" + e.getId());
//                        r.setName(PkgUtils.gen(e.getSeq()));
//                        r.setPid(reqVo.getId());
//                        r.setDeliveryDate(e.getPlanEndDateTime().toLocalDate());
//                        r.setIconCls(4);
//                        r.setFinishCount(new BigDecimal(e.getFinishQty()));
//                        r.setTotalCount(new BigDecimal(e.getOrderQty()));
//                        r.setUnit("架");
//                        return r;
//                    })
//                    .collect(Collectors.toList());
//
//            return new BaseListResVo<>(collect);
//        }
        return new BaseListResVo<>(Lists.newArrayList());
    }

    public BaseListResVo<ReportPartListResVo> partList(ReportPartListReqVo reqVo) {

        Map<Integer, String> map = new HashMap<>();
        map.put(1, "Assembly");
        map.put(2, "Platepart");
        map.put(3, "Component");

        List<ApsWorkOrder> workOrderList = null;
        if (StringUtils.hasText(reqVo.getId())) {
            String[] split = reqVo.getId().split("\\$");
            if (!(split[0].equals("4") || split[0].equals("3"))) {
                return BaseListResVo.empty();
            }

            ApsWorkOrder apsWorkOrder = null;

            Integer id = Integer.parseInt(split[1]);
            if (split[0].equals("4")) {
                apsWorkOrder = apsWorkOrderMapper.selectById(id);
            } else {
                apsWorkOrder = apsWorkOrderMapper.lambdaQuery()
                        .isNull(ApsWorkOrder::getPid)
                        .eq(ApsWorkOrder::getApsOrderId, id)
                        .one();
                reqVo.setChildren(true);
            }

            LambdaQueryChainWrapper<ApsWorkOrder> wrapper = apsWorkOrderMapper.lambdaQuery();

            if (reqVo.isChildren() && apsWorkOrder.getMaterType().equals("Assembly")) {

                ApsWorkOrder finalApsWorkOrder = apsWorkOrder;
                wrapper.and(w -> w.likeRight(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath() + "/").or().eq(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath()));
            } else {
                if (apsWorkOrder.getMaterType().equals("Assembly") && (reqVo.getType().equals(2) || reqVo.getType().equals(3))) {
                    wrapper.eq(ApsWorkOrder::getPid, Integer.parseInt(split[1]));
                } else {
                    if (reqVo.getType().equals(2) || reqVo.getType().equals(3)) {
                        wrapper.eq(ApsWorkOrder::getId, Integer.parseInt(split[1]));
                    }
                }
            }

            wrapper.eq(ApsWorkOrder::getApsOrderId, apsWorkOrder.getApsOrderId());
            wrapper.eq(ApsWorkOrder::getMaterType, map.get(reqVo.getType()));

            if (split[0].equals("3")) {
                ApsWorkOrder finalApsWorkOrder = apsWorkOrder;
                wrapper.and(w -> w.likeRight(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath() + "/").or().eq(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath()));
                wrapper.eq(!reqVo.isChildren(), ApsWorkOrder::getLevel, apsWorkOrder.getLevel());
            } else {
                ApsWorkOrder finalApsWorkOrder = apsWorkOrder;
                wrapper.and(w -> w.likeRight(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath() + "/").or().eq(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath()));
                wrapper.in(!reqVo.isChildren(), ApsWorkOrder::getLevel, apsWorkOrder.getLevel(), apsWorkOrder.getLevel() + 1);
            }

            workOrderList = wrapper.list();
        } else if (StringUtils.hasText(reqVo.getPlmId())) {

            List<Integer> orderIdList = null;
            if(StringUtils.hasText(reqVo.getConstructCode())){
                List<Order> orderList = orderMapper.lambdaQuery()
                        .like(Order::getConstructNo, reqVo.getConstructCode())
                        .list();
                orderIdList = orderList.stream().map(Order::getId).collect(Collectors.toList());
            }


            workOrderList = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getPlmId, reqVo.getPlmId())
                    .eq(StringUtils.hasText(map.get(reqVo.getType())), ApsWorkOrder::getMaterType, map.get(reqVo.getType()))
                    .in(CollUtil.isNotEmpty(orderIdList), ApsWorkOrder::getOrderId, orderIdList)
                    .in(ApsWorkOrder::getOrderType, 1, 3, 4)
                    .list();

        } else if (StringUtils.hasText(reqVo.getWorkOrderCode())) {
            List<Integer> orderIdList = null;
            if(StringUtils.hasText(reqVo.getConstructCode())){
                List<Order> orderList = orderMapper.lambdaQuery()
                        .like(Order::getConstructNo, reqVo.getConstructCode())
                        .list();
                orderIdList = orderList.stream().map(Order::getId).collect(Collectors.toList());
            }

            workOrderList = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getWorkOrderCode, reqVo.getWorkOrderCode())
                    .eq(StringUtils.hasText(map.get(reqVo.getType())), ApsWorkOrder::getMaterType, map.get(reqVo.getType()))
                    .in(CollUtil.isNotEmpty(orderIdList), ApsWorkOrder::getOrderId, orderIdList)
                    .in(ApsWorkOrder::getOrderType, 1, 3, 4)
                    .list();
        } else if (StringUtils.hasText(reqVo.getPickCode())) {
            workOrderList = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getPickCode, reqVo.getPickCode())
                    .eq(StringUtils.hasText(map.get(reqVo.getType())), ApsWorkOrder::getMaterType, map.get(reqVo.getType()))
                    .isNotNull(ApsWorkOrder::getPickCode)
                    .orderByAsc(ApsWorkOrder::getPickSeq)
                    .list();
        } else {
            throw SyExceptionUtils.e("查询错误，请检查参数");
        }

        if (CollUtil.isEmpty(workOrderList)) {
            return BaseListResVo.empty();
        }
        List<Integer> pidList = workOrderList.stream().map(ApsWorkOrder::getPid).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        Map<Integer, ApsWorkOrder> workOrderMap = new HashMap<>();
        if (!CollUtil.isEmpty(pidList)) {
            List<ApsWorkOrder> parentList = apsWorkOrderMapper.lambdaQuery().in(ApsWorkOrder::getId, pidList).list();
            workOrderMap = parentList.stream().collect(Collectors.toMap(ApsWorkOrder::getId, Function.identity()));

        }

        Map<Integer, ApsWorkOrder> workOrderMap1 = workOrderMap;

        List<Integer> apsOrderIdList = workOrderList.stream().map(ApsWorkOrder::getApsOrderId).distinct().collect(Collectors.toList());

        List<ApsOrder> apsOrderList = apsOrderMapper.selectBatchIds(apsOrderIdList);
        Map<Integer, ApsOrder> apsOrderMap = apsOrderList.stream().collect(Collectors.toMap(ApsOrder::getId, Function.identity()));

        List<Integer> orderIdList = workOrderList.stream().map(ApsWorkOrder::getOrderId).distinct().collect(Collectors.toList());
        List<Order> orderList = orderMapper.selectBatchIds(orderIdList);
        Map<Integer, Order> orderMap = orderList.stream().collect(Collectors.toMap(Order::getId, Function.identity()));

        workOrderList = workOrderList.stream().filter(e -> orderMap.containsKey(e.getOrderId())).collect(Collectors.toList());

        List<String> workOrderPlmIdList = workOrderList.stream().map(ApsWorkOrder::getPlmId).distinct().collect(Collectors.toList());
        List<OrderPart> orderPartList = orderPartMapper.lambdaQuery().in(OrderPart::getPlmId, workOrderPlmIdList).list();
        Map<String, OrderPart> orderPartMap = orderPartList.stream().collect(Collectors.toMap(OrderPart::getPlmId, Function.identity()));


        List<ReportPartListResVo> collect = workOrderList.stream()
                .map(e -> {
                    ReportPartListResVo r = new ReportPartListResVo();
                    BeanUtils.copyProperties(e, r, "id");
                    r.setId("4" + "$" + e.getId());
                    ApsOrder apsOrder = apsOrderMap.get(e.getApsOrderId());
                    r.setConstructCode(apsOrder.getConstructNo());
                    r.setPkgCode(PkgUtils.gen(apsOrder.getSeq()));
                    r.setWeight(e.getMaterWeight());

                    Order order = orderMap.get(e.getOrderId());
                    r.setSerialCode(order.getSerialCode());

                    if (e.getPid() != null) {
                        ApsWorkOrder p = workOrderMap1.get(e.getPid());
                        r.setParentMaterName(p.getPlmId());
                    }

                    if (StringUtils.hasText(e.getPickCode())) {
                        if (e.getFinishCount().compareTo(e.getOrderCount()) == 0) {
                            r.setPickCode(e.getPickCode() + "（X）");
                        } else {
                            r.setPickCode(e.getPickCode() + "（" + e.getFinishCount().intValue() + "/" + e.getOrderCount().intValue() + "）");
                        }
                    }
                    OrderPart orderPart = orderPartMap.get(e.getPlmId());
                    if (orderPart != null) {
                        r.setNestWeight(orderPart.getNetWeight());
                        r.setLength(orderPart.getLength());
                        r.setWidth(orderPart.getWidth());
                        if (StringUtils.hasText(orderPart.getDxfUrl())) {
                            r.setDrawStatus("X");
                        }
                    }

                    if (e.getMaterType().equals("Component") || e.getMaterType().equals("Platepart")) {
                        if(r.getNestWeight() != null){
                            r.setTotalWeight(r.getNestWeight().multiply(r.getTotalCount()));
                        }
                    }
                    r.setThickness(e.getMaterHigh());
                    r.setTexture(e.getTexture());
                    r.setStandards(e.getStandards());
                    r.setQualifiedStatus(null);

                    r.setSourceId(e.getId());
                    r.setPid(e.getPid());


                    return r;
                })
                .collect(Collectors.toList());


        List<ReportPartListResVo> ass = collect.stream().filter(e -> e.getMaterType().equals("Assembly")).sorted(Comparator.comparing(ReportPartListResVo::getLevel).reversed()).collect(Collectors.toList());

        if (CollUtil.isEmpty(ass)) {
            return new BaseListResVo<>(collect);
        }

        Optional<ReportPartListResVo> min = ass.stream().min(Comparator.comparing(ReportPartListResVo::getLevel));
        if (!min.isPresent()) {
            return new BaseListResVo<>(collect);
        }

        ReportPartListResVo minAss = min.get();

        ApsWorkOrder apsWorkOrder = apsWorkOrderMapper.selectById(minAss.getSourceId());


        ApsWorkOrder finalApsWorkOrder = apsWorkOrder;
        List<ApsWorkOrder> list = apsWorkOrderMapper.lambdaQuery()
                .eq(ApsWorkOrder::getApsOrderId, apsWorkOrder.getApsOrderId())
//                .ne(ApsWorkOrder::getMaterType, "Assembly")
                .and(w -> w.likeRight(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath() + "/").or().eq(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath()))
                .list();
        if(CollUtil.isEmpty(list)){
            return BaseListResVo.empty();
        }

        List<String> collect1 = list.stream().map(ApsWorkOrder::getPlmId).distinct().collect(Collectors.toList());
        List<OrderPart> orderPartList1 = orderPartMapper.lambdaQuery().in(OrderPart::getPlmId, collect1).list();
        Map<String, OrderPart> orderPatMap = orderPartList1.stream().collect(Collectors.toMap(OrderPart::getPlmId, Function.identity()));

        List<ReportPartListResVo> subRes = list.stream()
                .map(e -> {
                    ReportPartListResVo r = new ReportPartListResVo();
                    BeanUtils.copyProperties(e, r, "id");
                    r.setId("4" + "$" + e.getId());
                    ApsOrder apsOrder = apsOrderMap.get(e.getApsOrderId());
                    r.setConstructCode(apsOrder.getConstructNo());
                    r.setPkgCode(PkgUtils.gen(apsOrder.getSeq()));
                    r.setWeight(e.getMaterWeight());


                    if (StringUtils.hasText(e.getPickCode())) {
                        if (e.getFinishCount().compareTo(e.getOrderCount()) == 0) {
                            r.setPickCode(e.getPickCode() + "（X）");
                        } else {
                            r.setPickCode(e.getPickCode() + "（" + e.getFinishCount().intValue() + "/" + e.getOrderCount().intValue() + "）");
                        }
                    }

                    OrderPart orderPart = orderPatMap.get(e.getPlmId());
                    if (orderPart != null) {
                        r.setNestWeight(orderPart.getNetWeight());
                        r.setLength(orderPart.getLength());
                        r.setWidth(orderPart.getWidth());
                    }

                    if (e.getMaterType().equals("Component") || e.getMaterType().equals("Platepart")) {
                        if (r.getNestWeight() != null) {
                            r.setTotalWeight(r.getNestWeight().multiply(r.getTotalCount()));
                        }
                    }
                    r.setThickness(e.getMaterHigh());
                    r.setTexture(e.getTexture());
                    r.setStandards(e.getStandards());
                    r.setQualifiedStatus(null);

                    r.setSourceId(e.getId());
                    r.setPid(e.getPid());

                    return r;
                })
                .collect(Collectors.toList());


//        Assembly

        subRes.addAll(ass);
        Map<Integer, List<ReportPartListResVo>> parentGroupMap = subRes.stream().filter(e -> e.getPid() != null).collect(Collectors.groupingBy(ReportPartListResVo::getPid));

        for (ReportPartListResVo reportPartListResVo : ass) {
            List<ReportPartListResVo> reportPartListResVos = parentGroupMap.get(reportPartListResVo.getSourceId());

            if (reportPartListResVos != null) {

                BigDecimal reduce = reportPartListResVos.stream().map(ReportPartListResVo::getTotalWeight).filter(totalWeight -> totalWeight != null).reduce(BigDecimal.ZERO, BigDecimal::add);
                reportPartListResVo.setTotalWeight(reduce);
            }
        }


        return new BaseListResVo<>(collect);
    }

    public ReportPartStatResVo partCount(ReportPartStatReqVo reqVo) {
        if (StringUtils.hasText(reqVo.getPlmId())) {

            ReportPartStatResVo r = new ReportPartStatResVo();
            Integer componentTotal = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getPlmId, reqVo.getPlmId())
                    .eq(ApsWorkOrder::getMaterType, "Assembly")
                    .in(ApsWorkOrder::getOrderType, 1, 3, 4)
                    .count();
            r.setComponentTotal(componentTotal);

            Integer partTotal = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getPlmId, reqVo.getPlmId())
                    .eq(ApsWorkOrder::getMaterType, "Platepart")
                    .in(ApsWorkOrder::getOrderType, 1, 3, 4)
                    .count();
            r.setPartTotal(partTotal);

            Integer wlTotal = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getPlmId, reqVo.getPlmId())
                    .eq(ApsWorkOrder::getMaterType, "Component")
                    .in(ApsWorkOrder::getOrderType, 1, 3, 4)
                    .count();
            r.setWlTotal(wlTotal);

            return r;
        } else if (StringUtils.hasText(reqVo.getWorkOrderCode())) {
            ReportPartStatResVo r = new ReportPartStatResVo();
            Integer componentTotal = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getWorkOrderCode, reqVo.getWorkOrderCode())
                    .eq(ApsWorkOrder::getMaterType, "Assembly")
                    .count();
            r.setComponentTotal(componentTotal);

            Integer partTotal = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getWorkOrderCode, reqVo.getWorkOrderCode())
                    .eq(ApsWorkOrder::getMaterType, "Platepart")
                    .count();
            r.setPartTotal(partTotal);

            Integer wlTotal = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getWorkOrderCode, reqVo.getWorkOrderCode())
                    .eq(ApsWorkOrder::getMaterType, "Component")
                    .count();
            r.setWlTotal(wlTotal);

        } else if (StringUtils.hasText(reqVo.getPickCode())) {
            ReportPartStatResVo r = new ReportPartStatResVo();
            r.setComponentTotal(0);
            r.setPartTotal(0);

            Integer wlTotal = apsWorkOrderMapper.lambdaQuery()
                    .eq(ApsWorkOrder::getPickCode, reqVo.getPickCode())
                    .eq(ApsWorkOrder::getMaterType, "Component")
                    .count();
            r.setWlTotal(wlTotal);
        } else if (StringUtils.hasText(reqVo.getId())) {
            String[] split = reqVo.getId().split("\\$");
            if (!split[0].equals("4") && !split[0].equals("3")) {
                throw SyExceptionUtils.e("不支持的查询类型");
            }

            Map<Integer, String> map = new HashMap<>();
            map.put(1, "Assembly");
            map.put(2, "Platepart");
            map.put(3, "Component");

            Integer id = Integer.parseInt(split[1]);
            ApsWorkOrder apsWorkOrder = null;
            if (split[0].equals("3")) {
                apsWorkOrder = apsWorkOrderMapper.lambdaQuery()
                        .isNull(ApsWorkOrder::getPid)
                        .eq(ApsWorkOrder::getApsOrderId, id)
                        .one();
                reqVo.setChildren(true);
            } else {
                apsWorkOrder = apsWorkOrderMapper.selectById(id);

            }

            ReportPartStatResVo r = new ReportPartStatResVo();
            ApsWorkOrder finalApsWorkOrder = apsWorkOrder;
            Integer componentTotal = apsWorkOrderMapper.lambdaQuery()
//                    .likeRight(ApsWorkOrder::getAssemblyPath, apsWorkOrder.getAssemblyPath())
                    .and(w -> w.likeRight(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath() + "/").or().eq(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath()))
                    .eq(ApsWorkOrder::getApsOrderId, apsWorkOrder.getApsOrderId())
                    .eq(ApsWorkOrder::getMaterType, map.get(1))
                    .in(!reqVo.isChildren(), ApsWorkOrder::getLevel, apsWorkOrder.getLevel(), apsWorkOrder.getLevel() + 1)
                    .count();
            r.setComponentTotal(componentTotal);

            Integer partTotal = apsWorkOrderMapper.lambdaQuery()
//                    .likeRight(ApsWorkOrder::getAssemblyPath, apsWorkOrder.getAssemblyPath())
                    .and(w -> w.likeRight(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath() + "/").or().eq(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath()))
                    .eq(ApsWorkOrder::getApsOrderId, apsWorkOrder.getApsOrderId())
                    .eq(!reqVo.isChildren() && !apsWorkOrder.getMaterType().equals("Assembly"), ApsWorkOrder::getId, apsWorkOrder.getId())
                    .eq(!reqVo.isChildren() && apsWorkOrder.getMaterType().equals("Assembly"), ApsWorkOrder::getPid, apsWorkOrder.getId())
                    .eq(ApsWorkOrder::getMaterType, map.get(2))
                    .in(!reqVo.isChildren(), ApsWorkOrder::getLevel, apsWorkOrder.getLevel(), apsWorkOrder.getLevel() + 1)
                    .count();
            r.setPartTotal(partTotal);

            Integer wlTotal = apsWorkOrderMapper.lambdaQuery()
//                    .likeRight(ApsWorkOrder::getAssemblyPath, apsWorkOrder.getAssemblyPath())
                    .and(w -> w.likeRight(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath() + "/").or().eq(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath()))
                    .eq(ApsWorkOrder::getApsOrderId, apsWorkOrder.getApsOrderId())
                    .eq(ApsWorkOrder::getMaterType, map.get(3))
                    .eq(!reqVo.isChildren() && !apsWorkOrder.getMaterType().equals("Assembly"), ApsWorkOrder::getId, apsWorkOrder.getId())
                    .eq(!reqVo.isChildren() && apsWorkOrder.getMaterType().equals("Assembly"), ApsWorkOrder::getPid, apsWorkOrder.getId())
                    .in(!reqVo.isChildren(), ApsWorkOrder::getLevel, apsWorkOrder.getLevel(), apsWorkOrder.getLevel() + 1)
                    .count();
            r.setWlTotal(wlTotal);


            LambdaQueryChainWrapper<ApsWorkDetail> wrapper = apsWorkDetailMapper.lambdaQuery();
            if (split[0].equals("3")) {
                wrapper.eq(ApsWorkDetail::getApsOrderId, id);
            } else {
                apsWorkOrder = apsWorkOrderMapper.selectById(id);

                List<ApsWorkOrder> apsWorkOrderList = apsWorkOrderMapper.lambdaQuery()
//                        .likeRight(ApsWorkOrder::getAssemblyPath, apsWorkOrder.getAssemblyPath())
                        .and(w -> w.likeRight(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath() + "/").or().eq(ApsWorkOrder::getAssemblyPath, finalApsWorkOrder.getAssemblyPath()))
                        .eq(ApsWorkOrder::getApsOrderId, apsWorkOrder.getApsOrderId())
                        .in(!reqVo.isChildren(), ApsWorkOrder::getLevel, apsWorkOrder.getLevel(), apsWorkOrder.getLevel() + 1)
                        .list();

                List<Integer> idList = apsWorkOrderList.stream().map(BaseEntity::getId).distinct().collect(Collectors.toList());

                wrapper.in(ApsWorkDetail::getApsWorkOrderId, idList);
            }
            wrapper.select(ApsWorkDetail::getPhaseCode);
            wrapper.groupBy(ApsWorkDetail::getPhaseCode);
            List<ApsWorkDetail> list = wrapper.list();

            r.setAbilityTotal(list.size());

            return r;
        }

        return null;
    }

    public BaseListResVo<ReportProOrderListResVo> proOrderList(ReportProOrderListReqVo reqVo) {

        Map<Integer, String> orderTypeMap = new HashMap<>();
        orderTypeMap.put(1, "1");
        orderTypeMap.put(4, "11");
        orderTypeMap.put(3, "21");

        if (StringUtils.hasText(reqVo.getSerialCode())) {
            LambdaQueryChainWrapper<Order> wrapper = orderMapper.lambdaQuery();
            wrapper.like(Order::getSerialCode, reqVo.getSerialCode());
            wrapper.ge(Order::getOrderStatus, 6);
            List<Order> orderList = wrapper.list();

            if (CollUtil.isEmpty(orderList)) {
                return BaseListResVo.empty();
            }

            QueryWrapper<ApsOrder> wrapper1 = Wrappers.query();
            wrapper1.in("order_id", orderList.stream().map(BaseEntity::getId).collect(Collectors.toList()));
            wrapper1.groupBy("order_id");
            List<ApsOrder> apsOrderList = apsOrderMapper.selectPack(wrapper1);

            Map<Integer, ApsOrder> collect1 = apsOrderList.stream().collect(Collectors.toMap(ApsOrder::getOrderId, Function.identity()));


            List<ReportProOrderListResVo> collect = orderList.stream()
                    .map(e -> {
                        ReportProOrderListResVo r = new ReportProOrderListResVo();
                        BeanUtils.copyProperties(e, r);
                        r.setPkgTotal(collect1.get(e.getId()).getSeq());
                        r.setMaterName(e.getMaterName());
                        String s = orderTypeMap.get(e.getOrderType());

                        r.setId("2$" + e.getId());

                        return r;
                    })
                    .collect(Collectors.toList());
            return new BaseListResVo<>(collect);
        }


        String[] split = reqVo.getId().split("\\$");

        LambdaQueryChainWrapper<Order> wrapper = orderMapper.lambdaQuery();

        if (split[0].equals("1")) {
            wrapper.eq(Order::getOrderType, 1);
            if (Boolean.TRUE.equals(reqVo.getHistory())) {
                wrapper.le(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            } else {
                wrapper.gt(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            }
        } else if (split[0].equals("11")) {
            wrapper.eq(Order::getOrderType, 4);
            if (Boolean.TRUE.equals(reqVo.getHistory())) {
                wrapper.le(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            } else {
                wrapper.gt(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            }
        } else if (split[0].equals("21")) {
            wrapper.eq(Order::getOrderType, 3);
            if (Boolean.TRUE.equals(reqVo.getHistory())) {
                wrapper.le(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            } else {
                wrapper.gt(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
            }
        } else if (split[0].equals("2") || split[0].equals("12") || split[0].equals("22")) {
            Integer id = Integer.parseInt(split[1]);
            wrapper.eq(Order::getId, id);
        }

        wrapper.ge(Order::getOrderStatus, 6);
        List<Order> orderList = wrapper.list();

        if (CollUtil.isEmpty(orderList)) {
            return BaseListResVo.empty();
        }

        QueryWrapper<ApsOrder> wrapper1 = Wrappers.query();
        wrapper1.in("order_id", orderList.stream().map(BaseEntity::getId).collect(Collectors.toList()));
        wrapper1.groupBy("order_id");
        List<ApsOrder> apsOrderList = apsOrderMapper.selectPack(wrapper1);

        Map<Integer, ApsOrder> collect1 = apsOrderList.stream().collect(Collectors.toMap(ApsOrder::getOrderId, Function.identity()));


        List<ReportProOrderListResVo> collect = orderList.stream().map(e -> {
            ReportProOrderListResVo r = new ReportProOrderListResVo();
            BeanUtils.copyProperties(e, r);
            r.setPkgTotal(collect1.get(e.getId()).getSeq());
            r.setMaterName(e.getMaterName());
            String s = orderTypeMap.get(e.getOrderType());

            r.setId(s + "$" + e.getId());

            return r;
        }).collect(Collectors.toList());

        return new BaseListResVo<>(collect);
    }

    public BaseListResVo<ReportProSubListResVo> proSubList(ReportProSubListReqVo reqVo) {
        String[] split = reqVo.getId().split("\\$");
        if (!split[0].equals("2")) {
            return BaseListResVo.empty();
        }

        Integer id = Integer.parseInt(split[1]);
        Order order = orderMapper.selectById(id);
        List<ApsOrder> orderList = apsOrderMapper.lambdaQuery().eq(ApsOrder::getOrderId, id).list();

        List<ReportProSubListResVo> collect = orderList.stream()
                .map(e -> {
                    ReportProSubListResVo r = new ReportProSubListResVo();
                    r.setSerialCode(order.getSerialCode());
                    r.setPkgCode(PkgUtils.gen(e.getSeq()));
                    r.setPlanEndDateTime(e.getPlanEndDateTime());
                    r.setActualEndDateTime(e.getActualFinishTime());
                    return r;
                })
                .collect(Collectors.toList());

        return new BaseListResVo<>(collect);
    }

    public ReportProOrderStatResVo proOrderStat(ReportProOrderStatReqVo reqVo) {
        LambdaQueryChainWrapper<Order> wrapper = orderMapper.lambdaQuery();

        if (StringUtils.hasText(reqVo.getSerialCode())) {
            wrapper.like(Order::getSerialCode, reqVo.getSerialCode());
            wrapper.ge(Order::getOrderStatus, 6);
            Integer orderCount = wrapper.count();
            ReportProOrderStatResVo r = new ReportProOrderStatResVo();
            r.setOrderTotal(orderCount);
            r.setSubOrderTotal(0);
            return r;
        } else {
            String[] split = reqVo.getId().split("\\$");

            Map<String, Integer> map = new HashMap<>();
            map.put("1", 1);
            map.put("11", 4);
            map.put("21", 3);

            if (split[0].equals("1") || split[0].equals("11") || split[0].equals("21")) {
                wrapper.in(Order::getOrderType, map.get(split[0]));
                if (Boolean.TRUE.equals(reqVo.getHistory())) {
                    wrapper.le(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
                } else {
                    wrapper.gt(Order::getDeliveryDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER));
                }
            }


            if (split[0].equals("2")) {
                Integer id = Integer.parseInt(split[1]);
                wrapper.eq(Order::getId, id);
            }

            wrapper.ge(Order::getOrderStatus, 6);
            Integer orderCount = wrapper.count();

            ReportProOrderStatResVo r = new ReportProOrderStatResVo();
            r.setOrderTotal(orderCount);


            // 施工号
            if (split[0].equals("2") || split[0].equals("12") || split[0].equals("22")) {

                Integer id = Integer.parseInt(split[1]);
                Integer count = apsOrderMapper.lambdaQuery().eq(ApsOrder::getOrderId, id).count();
                r.setSubOrderTotal(count);
            } else {
                r.setSubOrderTotal(0);
            }
            return r;

        }

    }

    public BaseListResVo<ReportProPhaseResVo> proPhase(ReportProPhaseReqVo reqVo) {

        String[] split = reqVo.getId().split("\\$");
        if (!split[0].equals("4")) {
            throw SyExceptionUtils.e("类型不匹配");
        }

        ApsWorkOrder workOrder = apsWorkOrderMapper.lambdaQuery()
                .eq(ApsWorkOrder::getId, Integer.parseInt(split[1]))
                .one();

        if (workOrder.getWorkChain().equals("WL")) {
            ReportProPhaseResVo r = new ReportProPhaseResVo();
            r.setPhaseName("外购件");
            r.setPhaseCode("WL");
            r.setPhaseSeq(1);
            r.setGroupCode("-");
            r.setOrderCount(workOrder.getOrderCount());
            r.setFinishCount(workOrder.getFinishCount());
            r.setWorkTime(new BigDecimal(0));
            r.setTotalTime(new BigDecimal(0));
            r.setPlanStartDateTime(workOrder.getPlanStartDateTime());
            r.setPlanEndDateTime(workOrder.getPlanStartDateTime());
            r.setActualEndDateTime(workOrder.getActualEndDateTime());
            r.setStatus(workOrder.getStatus());
            return new BaseListResVo<>(Arrays.asList(r));
        }

        Integer id = Integer.parseInt(split[1]);
        List<ApsWorkDetail> apsWorkDetailList = apsWorkDetailMapper.lambdaQuery()
                .eq(ApsWorkDetail::getApsWorkOrderId, id)
                .list();

        if (CollUtil.isEmpty(apsWorkDetailList)) {
            return BaseListResVo.empty();
        }

        List<String> collect1 = apsWorkDetailList.stream().map(ApsWorkDetail::getGroupCode).collect(Collectors.toList());

        List<Group> list = groupMapper.lambdaQuery().in(Group::getMyCode, collect1).list();
        Map<String, Group> groupMap = list.stream().collect(Collectors.toMap(Group::getMyCode, Function.identity()));


        List<ReportProPhaseResVo> collect = apsWorkDetailList.stream()
                .map(e -> {
                    ReportProPhaseResVo r = new ReportProPhaseResVo();
                    r.setPhaseName(e.getPhaseName());
                    r.setPhaseCode(e.getPhaseCode());
                    r.setPhaseSeq(e.getPhaseSeq());
                    r.setGroupCode(e.getGroupCode());
                    if (groupMap.get(e.getGroupCode()) != null) {
                        r.setGroupLabel(groupMap.get(e.getGroupCode()).getRemark());
                    }
                    r.setOrderCount(e.getTotalCount());
                    r.setFinishCount(e.getFinishCount());
                    r.setWorkTime(new BigDecimal(e.getWorkTime()).divide(new BigDecimal(60), 2, RoundingMode.HALF_UP));
                    r.setTotalTime(r.getWorkTime().multiply(r.getOrderCount()));
                    r.setPlanStartDateTime(e.getPlanStartDateTime());
                    r.setPlanEndDateTime(e.getPlanEndDateTime());
                    r.setActualEndDateTime(e.getActualEndDateTime());
                    r.setStatus(e.getStatus());
                    return r;
                })
                .collect(Collectors.toMap(ReportProPhaseResVo::getPhaseCode, Function.identity(), (k, v) -> {
                    k.setOrderCount(k.getOrderCount().add(v.getOrderCount()));
                    k.setFinishCount(k.getFinishCount().add(v.getFinishCount()));
                    if (k.getErrorCount() == null) {
                        k.setErrorCount(new BigDecimal(0));
                    }
                    if (v.getErrorCount() == null) {
                        v.setErrorCount(new BigDecimal(0));
                    }
                    k.setErrorCount(k.getErrorCount().add(v.getErrorCount()));
                    k.setWorkTime(k.getWorkTime());
                    k.setTotalTime(k.getTotalTime().add(v.getTotalTime()));
                    if (!k.getPlanStartDateTime().isBefore(v.getPlanStartDateTime())) {
                        k.setPlanStartDateTime(v.getPlanStartDateTime());
                    }

                    return k;
                }))
                .values()
                .stream()
                .sorted(Comparator.comparing(ReportProPhaseResVo::getPhaseSeq))
                .collect(Collectors.toList());

//        if (workOrder.getMaterType().equals("Platepart")) {
//            ReportProPhaseResVo lastPhase = collect.get(collect.size() - 1);
//            ReportProPhaseResVo r = new ReportProPhaseResVo();
//            BeanUtils.copyProperties(lastPhase, r);
//            r.setPhaseName("库检");
//            r.setPhaseCode("KJ");
//            r.setGroupCode("2-4_KJGW_00");
//            r.setGroupLabel("KJ");
//            r.setTotalTime(new BigDecimal(0));
//            r.setWorkTime(0);
//            r.setPlanStartDateTime(workOrder.getPlanEndDateTime());
//            r.setPhaseSeq(r.getPhaseSeq() + 1);
//
//            collect.add(r);
//        }

        return new BaseListResVo<>(collect);
    }

    public BaseListResVo<ReportProPlateResVo> proPlate(ReportProPlateReqVo reqVo) {
        String[] split = reqVo.getId().split("\\$");
        if (!split[0].equals("4")) {
            throw SyExceptionUtils.e("类型不匹配");
        }

        Integer id = Integer.parseInt(split[1]);

        ApsWorkOrder workOrder = apsWorkOrderMapper.selectById(id);

        List<ApsWorkDetail> list = null;

        if (workOrder.getMaterType().equals("Platepart")) {
            list = apsWorkDetailMapper.lambdaQuery()
                    .eq(ApsWorkDetail::getApsWorkOrderId, id)
                    .list();
        } else {
            List<ApsWorkOrder> workOrderList = apsWorkOrderMapper.lambdaQuery()
//                    .likeRight(ApsWorkOrder::getAssemblyPath, workOrder.getAssemblyPath())
                    .and(w -> w.likeRight(ApsWorkOrder::getAssemblyPath, workOrder.getAssemblyPath() + "/").or().eq(ApsWorkOrder::getAssemblyPath, workOrder.getAssemblyPath()))
                    .eq(ApsWorkOrder::getMaterType, "Platepart")
                    .list();
            if (CollUtil.isEmpty(workOrderList)) {
                list = new ArrayList<>();
            } else {
                list = apsWorkDetailMapper.lambdaQuery()
                        .in(ApsWorkDetail::getApsWorkOrderId, workOrderList.stream().map(BaseEntity::getId).collect(Collectors.toList()))
                        .in(ApsWorkDetail::getPhaseCode, "JG", "HG")
                        .eq(ApsWorkDetail::getApsOrderId, workOrder.getApsOrderId())
                        .list();
            }
        }

        if (CollUtil.isEmpty(list)) {
            return BaseListResVo.empty();
        }
        List<String> collect = list.stream().map(e -> String.valueOf(e.getId())).distinct().collect(Collectors.toList());


        List<SinoCamReceiveNestPart> list1 = sinoCamReceiveNestPartMapper.lambdaQuery().in(SinoCamReceiveNestPart::getNestPlanId, collect).list();
        if (CollUtil.isEmpty(list1)) {
            return BaseListResVo.empty();
        }

        List<String> collect1 = list1.stream().map(SinoCamReceiveNestPart::getNestId).distinct().collect(Collectors.toList());

        List<SinoCamReceiveNestPlate> list2 = sinoCamReceiveNestPlateMapper.lambdaQuery().in(SinoCamReceiveNestPlate::getNestId, collect1).list();

        Map<Integer, List<SinoCamReceiveNestPart>> partMap = list1.stream().collect(Collectors.groupingBy(SinoCamReceiveNestPart::getReceiveNestId));

        List<SinoCamReceiveNestNest> list3 = sinoCamReceiveNestNestMapper.lambdaQuery().in(SinoCamReceiveNestNest::getNestId, collect1).list();
        Map<String, SinoCamReceiveNestNest> nestMap = list3.stream().collect(Collectors.toMap(SinoCamReceiveNestNest::getNestId, Function.identity()));

        List<ApsWorkDetail> platePhaseList = apsWorkDetailMapper.lambdaQuery()
                .in(ApsWorkDetail::getMaterNo, list2.stream().map(SinoCamReceiveNestPlate::getStockListNo).collect(Collectors.toList()))
                .eq(ApsWorkDetail::getType, 1)
                .list();
        Map<String, List<ApsWorkDetail>> platePhaseMap = platePhaseList.stream().collect(Collectors.groupingBy(ApsWorkDetail::getMaterNo));

        List<WmsPlatePick> platePickList = wmsPlatePickMapper.lambdaQuery().in(WmsPlatePick::getMaterialId, list2.stream().map(SinoCamReceiveNestPlate::getStockListNo).distinct().collect(Collectors.toList())).list();
        Map<String, WmsPlatePick> platePickMap = platePickList.stream().collect(Collectors.toMap(WmsPlatePick::getMaterialId, Function.identity()));
        List<WmsPlatePick> allPlatePickList = wmsPlatePickMapper.lambdaQuery().in(WmsPlatePick::getPickingListNo, platePickList.stream().map(WmsPlatePick::getPickingListNo).distinct().collect(Collectors.toList())).list();
        Map<String, List<WmsPlatePick>> allPlatePickMap = allPlatePickList.stream().collect(Collectors.groupingBy(WmsPlatePick::getPickingListNo));

        List<WorkDetailTask> workDetailTaskList = workDetailTaskMapper.lambdaQuery()
                .in(WorkDetailTask::getMaterCode, list2.stream().map(SinoCamReceiveNestPlate::getStockListNo).distinct().collect(Collectors.toList()))
                .in(WorkDetailTask::getPhaseCode, "JG", "HG")
                .eq(WorkDetailTask::getType, 1)
                .list();
        Map<String, WorkDetailTask> taskMap = workDetailTaskList.stream().collect(Collectors.toMap(e -> e.getMaterCode(), Function.identity()));


        List<ReportProPlateResVo> resVoList = list2.stream()
                .map(e -> {
                    ReportProPlateResVo r = new ReportProPlateResVo();
                    r.setPlateCode(e.getStockListNo());
                    r.setHeatNumber(e.getHeatNumber());
                    r.setTexture(e.getTexture());
                    r.setNorm(e.getNorm());
                    r.setWidth(e.getWidth());
                    r.setLength(e.getLength());
                    List<SinoCamReceiveNestPart> sinoCamReceiveNestParts = partMap.get(e.getReceiveNestId());
                    if (CollUtil.isNotEmpty(sinoCamReceiveNestParts)) {
                        int i = sinoCamReceiveNestParts.stream().reduce(0, (a, b) -> a + b.getQuantity(), Integer::sum);
                        r.setQuantity(i);

                        int fjCount = sinoCamReceiveNestParts.stream().reduce(0, (a, b) -> a + b.getSortingCount(), Integer::sum);
                        r.setFjCount(fjCount);
                    }

                    List<ApsWorkDetail> platePhaseList1 = platePhaseMap.get(e.getStockListNo());
                    WorkDetailTask workDetailTask = taskMap.get(e.getStockListNo());
                    if (!CollectionUtils.isEmpty(platePhaseList1)) {
                        ApsWorkDetail llPhase = platePhaseList1.stream().filter(e1 -> e1.getPhaseCode().equals("LL")).findFirst().orElseGet(ApsWorkDetail::new);
                        r.setLlDateTime(llPhase.getActualEndDateTime());

                        ApsWorkDetail splitPhase = platePhaseList1.stream().filter(e1 -> e1.getPhaseCode().equals("JG") || e1.getPhaseCode().equals("HG")).findFirst().orElseGet(ApsWorkDetail::new);
                        r.setSplitDateTime(splitPhase.getActualEndDateTime());

                        ApsWorkDetail ycPhase = platePhaseList1.stream().filter(e1 -> e1.getPhaseCode().equals("YC")).findFirst().orElseGet(ApsWorkDetail::new);
                        r.setYcDateTime(ycPhase.getActualEndDateTime());

                        ApsWorkDetail fjPhase = platePhaseList1.stream().filter(e1 -> e1.getPhaseCode().equals("FJ")).findFirst().orElseGet(ApsWorkDetail::new);
                        r.setFjDateTime(fjPhase.getActualEndDateTime());
                        if (workDetailTask == null) {
                            r.setSplitGroupCode(splitPhase.getGroupCode());
                        } else {
                            r.setSplitGroupCode(workDetailTask.getStationCode());
                        }
                    }


                    r.setStorehouseId(e.getStorehouseId());
                    SinoCamReceiveNestNest sinoCamReceiveNestNest = nestMap.get(e.getNestId());
                    r.setNestId(sinoCamReceiveNestNest.getNestId());

                    WmsPlatePick wmsPlatePick = platePickMap.get(e.getStockListNo());
                    r.setPickCode(wmsPlatePick.getPickingListNo());
                    r.setNetWeight(wmsPlatePick.getPlateWeight());

                    List<WmsPlatePick> pickList = allPlatePickMap.get(wmsPlatePick.getPickingListNo());
                    if (CollUtil.isNotEmpty(pickList)) {

                        long count2 = pickList.stream()
                                .filter(e1 -> e1.getPlateState() >= 4)
                                .count();

                        long allCount = pickList.size();

                        if (pickList.size() == count2) {
                            r.setPickCode(r.getPickCode() + "(X)");
                        } else {
                            r.setPickCode(r.getPickCode() + "(" + count2 + "/" + allCount + ")");
                        }


                    } else {
                        r.setPickCode("/");
                    }

//                    if (e.getPlaStatus().equals(3)) {
//                        e.setRequisition(e.getRequisition() + "(0/1)");
//                    } else if (e.getPlaStatus() >= 4) {
//                        e.setRequisition(e.getRequisition() + "(X)");
//                    }

                    return r;
                })
                .collect(Collectors.toList());

        return new BaseListResVo<>(resVoList);
    }

    public BaseListResVo<ReportProStockResVo> proStock(ReportProStockReqVo reqVo) {
        String[] split = reqVo.getId().split("\\$");
        if (!split[0].equals("4")) {
            throw SyExceptionUtils.e("类型不匹配");
        }

        Integer id = Integer.parseInt(split[1]);
        ApsWorkOrder workOrder = apsWorkOrderMapper.selectById(id);
        if (!workOrder.getMaterType().equals("Platepart")) {
            return BaseListResVo.empty();
        }


        List<PartPallet> list = partPalletMapper.lambdaQuery()
                .eq(PartPallet::getPlmId, workOrder.getPlmId())
                .list();

        List<ReportProStockResVo> collect = list.stream()
                .map(e -> {
                    ReportProStockResVo r = new ReportProStockResVo();
                    r.setPlmId(e.getPlmId());
                    r.setPhaseCode(e.getPrePhaseCode());
                    r.setNextPhaseCode(e.getPhaseCode());
                    r.setTotalCount(e.getPartCount());
                    r.setUniqueCode(e.getUniqueCode());
                    if (e.getType().equals(1)) {
                        r.setPalletCode(e.getLoadingCode());
                    } else if (e.getType().equals(2)) {
                        r.setLoadingCode(e.getPositionCode());
                    } else {
                        r.setPalletCode(e.getPositionCode());
                        r.setLoadingCode(e.getPositionCode());
                    }
                    r.setNextGroupCode(null);
                    r.setCreateDateTime(e.getCreateDateTime());
                    return r;
                })
                .collect(Collectors.toList());


        List<Part> list1 = partMapper.lambdaQuery()
                .eq(Part::getPlmId, workOrder.getPlmId())
                .list();

        List<ReportProStockResVo> collect1 = list1.stream().map(e -> {
            ReportProStockResVo r = new ReportProStockResVo();
            r.setPlmId(e.getPlmId());
            r.setPhaseCode(e.getPrePhaseCode());
            r.setNextPhaseCode(e.getPhaseCode());
            int i = list.stream().filter(e1 -> e1.getPhaseCode().equals(e.getPhaseCode())).map(PartPallet::getPartCount).reduce(0, Integer::sum).intValue();
            r.setTotalCount(e.getPartCount() - i);
            r.setNextGroupCode(null);
            r.setCreateDateTime(e.getCreateDateTime());
            return r;
        }).collect(Collectors.toList());
        collect.addAll(collect1);
        return new BaseListResVo<>(collect);
    }

    public ReportProPartDrawResVo proPartDraw(ReportProPartDrawReqVo reqVo) {
        String[] split = reqVo.getId().split("\\$");
        if (!split[0].equals("4")) {
            throw SyExceptionUtils.e("类型不匹配");
        }

        Integer id = Integer.parseInt(split[1]);
        ApsWorkOrder task = apsWorkOrderMapper.selectById(id);

        String code = task.getPlmId();

//        SinoCamReceiveNestPart nestPart = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getPartId, code).last(" limit 1 ").one();
//        String url = "";
//        if (nestPart != null) {
//            url = String.format(projectConfig.getUrlPre(), nestPart.getPartId(), nestPart.getPartMapUrl());
//        }

        OrderPart orderPart = orderPartMapper.lambdaQuery().eq(OrderPart::getPlmId, code).one();

        ReportProPartDrawResVo r = new ReportProPartDrawResVo();
        if (orderPart != null && StringUtils.hasText(orderPart.getPngUrl())) {
            r.setPartPngUrl(String.format(projectConfig.getUrlPre(), orderPart.getPlmId() + ".png", orderPart.getPngUrl()));
        }
//        r.setPartPngUrl(orderPart.getPngUrl());
        return r;
    }

    public BaseListResVo<ReportProAssemblyResVo> proAssembly(ReportProAssemblyReqVo reqVo) {

        String[] split = reqVo.getId().split("\\$");
        if (!split[0].equals("4")) {
            throw SyExceptionUtils.e("类型不匹配");
        }

        Integer id = Integer.parseInt(split[1]);
        ApsWorkOrder workOrder = apsWorkOrderMapper.selectById(id);
        if (!workOrder.getMaterType().equals("Assembly")) {
            return BaseListResVo.empty();
        }

        List<ApsWorkDetail> workDetailList = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getApsWorkOrderId, id).list();
        ApsWorkDetail minDetail = workDetailList.stream().distinct().min(Comparator.comparing(ApsWorkDetail::getPhaseSeq)).get();
        ApsWorkDetail maxDetail = workDetailList.stream().distinct().max(Comparator.comparing(ApsWorkDetail::getPhaseSeq)).get();

        List<String> uniqueCodeList = workDetailList.stream().map(ApsWorkDetail::getUniqueCode).filter(StringUtils::hasText).distinct().collect(Collectors.toList());

        Map<String, PartPallet> partPalletMap = new HashMap<>();
        if (CollUtil.isNotEmpty(uniqueCodeList)) {
            List<PartPallet> partPalletList = partPalletMapper.lambdaQuery().in(PartPallet::getUniqueCode, uniqueCodeList).list();
            partPalletMap = partPalletList.stream().collect(Collectors.toMap(PartPallet::getUniqueCode, Function.identity()));
        }

        List<ApsWorkDetail> workRootDetailList = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getApsWorkOrderId, workOrder.getPid()).list();
//        ApsWorkDetail minRootDetail = workRootDetailList.stream().distinct().min(Comparator.comparing(ApsWorkDetail::getPhaseSeq)).get();
        Optional<ApsWorkDetail> max = workRootDetailList.stream().distinct().max(Comparator.comparing(ApsWorkDetail::getPhaseSeq));
        if (!max.isPresent()) {
            return BaseListResVo.empty();

        }
        ApsWorkDetail maxRootDetail = max.get();

        Map<String, PartPallet> finalPartPalletMap = partPalletMap;
        List<ReportProAssemblyResVo> collect1 = workDetailList.stream()
                .filter(e -> e.getPhaseSeq().equals(minDetail.getPhaseSeq()))
                .map(e -> {
                    ReportProAssemblyResVo r = new ReportProAssemblyResVo();
                    r.setPlmId(workOrder.getPlmId());
                    r.setQuantity(e.getTotalCount());

                    PartPallet partPallet = finalPartPalletMap.get(e.getUniqueCode());
                    if (partPallet != null) {
                        r.setStoreCode(partPallet.getPositionCode());
                        r.setStoreType(partPallet.getType());
                    }
                    r.setWeight(null);
                    r.setUniqueCode(e.getUniqueCode());
                    if (!StringUtils.hasText(r.getUniqueCode())) {
                        r.setStatus(1);
                        return r;
                    }

                    boolean present = workDetailList.stream()
                            .anyMatch(ee -> ee.getPhaseSeq().equals(maxDetail.getPhaseSeq()) && ee.getUniqueCode().equals(e.getUniqueCode()));
                    if (!present) {
                        r.setStatus(2);
                        return r;
                    }

                    List<ApsWorkDetail> collect = workRootDetailList.stream().filter(e1 -> e.getUniqueCode().equals(e1.getUniqueCode())).collect(Collectors.toList());

                    // 已完工：组件工序链在当前层级走完，未被高一级组件开工时的状态；
                    if (CollUtil.isEmpty(collect)) {
                        r.setStatus(3);
                        return r;
                    }

                    // 被使用：组件工序链在当前层级走完，已被高一级组件开工时的状态；
                    if (!collect.stream().anyMatch(e1 -> e1.getPhaseSeq().equals(maxRootDetail.getPhaseSeq()))) {
                        r.setStatus(4);
                        return r;
                    }

                    // 已结束：组件工序链在当前层级走完，已被高一级组件开工，且完成高一级所有工序时的状态；
                    r.setStatus(5);
                    return r;
                })
                .collect(Collectors.toList());


        return new BaseListResVo<>(collect1);
    }

    public BaseListResVo<ReportPickListResVo> pickList(ReportPickListReqVo reqVo) {

        Map<String, String> compareType = reqVo.getQueryType();

        QueryWrapper<WmsPlatePick> wrapper = Wrappers.query();
//        wrapper.eq("plate_state", 4);
//        wrapper.eq("pick.material_id", "15_060_LG_24_01229");

        wrapper.and(CollUtil.isNotEmpty(reqVo.getGroupCodes()), e -> {
            for (String groupCode : reqVo.getGroupCodes()) {
                e.like("awd.group_code", groupCode);
                e.or();
            }
        });
        if (ObjectUtils.isNotEmpty(reqVo.getLength())) {
            WrapperUtil.fixWrapper(wrapper, "nest_plate.length", compareType.get("length"), reqVo.getLength());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getWidth())) {
            WrapperUtil.fixWrapper(wrapper, "nest_plate.width", compareType.get("width"), reqVo.getWidth());
        }
        if (ObjectUtils.isNotEmpty(reqVo.getThickness())) {
            WrapperUtil.fixWrapper(wrapper, "nest_plate.norm", compareType.get("thickness"), reqVo.getThickness());
        }

        wrapper.like(StringUtils.hasText(reqVo.getPickingListNo()), "pick.picking_list_no", reqVo.getPickingListNo());
        wrapper.like(StringUtils.hasText(reqVo.getNestId()), "nest_nest.nest_id", reqVo.getNestId());
        wrapper.like(StringUtils.hasText(reqVo.getPlateCode()), "pick.material_id", reqVo.getPlateCode());
        wrapper.like(StringUtils.hasText(reqVo.getStoreCode()), "pick.storage_place", reqVo.getStoreCode());
        wrapper.like(StringUtils.hasText(reqVo.getSpec()), "nest_plate.texture", reqVo.getSpec());
//        wrapper.eq(reqVo.getThickness() != null, "nest_plate.norm", reqVo.getThickness());

        wrapper.eq(reqVo.getSeq() != null, "nest_plate.sequence", reqVo.getSeq());

        wrapper.ge(reqVo.getPlanStartDate() != null, "nest_nest.need_date", reqVo.getPlanStartDate() + " 00:00:00");
        wrapper.le(reqVo.getPlanEndDate() != null, "nest_nest.need_date", reqVo.getPlanEndDate() + " 23:59:59");

        if (reqVo.getStatus() != null) {
            if (reqVo.getStatus().equals(1)) {
                wrapper.eq("pick.plate_state", 1);
                wrapper.isNull("pick.pick_id");
            } else if (reqVo.getStatus().equals(2)) {
                wrapper.eq("pick.plate_state", 1);
                wrapper.isNotNull("pick.pick_id");
            } else if (reqVo.getStatus().equals(3)) {
                wrapper.eq("pick.plate_state", 2);
                wrapper.isNotNull("pick.pick_id");
            } else if (reqVo.getStatus().equals(4)) {
                wrapper.ge("pick.plate_state", 4);
                wrapper.isNotNull("pick.pick_id");
            }
        }

        /*
        //添加排序条件
        String orderStr = "nest_nest.need_date";
        if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(reqVo.getSort())) {
            if ("planStartDate".equals(reqVo.getSort())) {
                orderStr = "det.plan_start_date_time";
            } else if ("planEndDate".equals(reqVo.getSort())) {
                orderStr = "det.plan_end_date_time";
            } else if ("startTime".equals(reqVo.getSort())) {
                orderStr = "det.actual_start_date_time";
            } else if ("endTime".equals(reqVo.getSort())) {
                orderStr = "det.actual_end_date_time";
            }
        }
        if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(reqVo.getOrder())) {
            if ("desc".equals(reqVo.getOrder())) {
                wrapper.orderByDesc(orderStr);
            } else {
                wrapper.orderByAsc(orderStr);
            }
        } else {
            wrapper.orderByAsc(orderStr);
        }
         */

        if (reqVo.getPlateStatus() != null && reqVo.getPlateStatus() < 6) {
            wrapper.lt("plate.status", 6);
        } else if (reqVo.getPlateStatus() != null) {
            wrapper.ge("plate.status", 6);
        }

        wrapper.last(" limit 1000 ");

        List<ReportPickListResVo> page = wmsPlatePickMapper.pickList(wrapper);
        if (CollUtil.isEmpty(page)) {
            return BaseListResVo.empty();
        }

        List<PlatePhase> platePhaseList = platePhaseMapper.lambdaQuery().in(PlatePhase::getPlateCode, page.stream().map(ReportPickListResVo::getPlateCode).collect(Collectors.toList())).list();
        Map<String, List<PlatePhase>> platePhaseMap = platePhaseList.stream().collect(Collectors.groupingBy(PlatePhase::getPlateCode));

        for (ReportPickListResVo record : page) {

            record.setLength(record.getLength().setScale(2, RoundingMode.HALF_UP));
            record.setWidth(record.getWidth().setScale(2, RoundingMode.HALF_UP));

            if (record.getPlateStatus() < 6 && record.getPlateStatus() > 0) {
                record.setPlateStatus(1);
            }


            StringBuilder sb = new StringBuilder();
//            if(StringUtils.hasText(record.getPickingListNo())){
//                sb.append(record.getPickingListNo());
//            }

            if (record.getStatus().equals(1)) {
                if (record.getPickId() == null) {
                    record.setStatus(1);
                } else {
                    record.setStatus(2);
                }
            } else if (record.getStatus().equals(2)) {
                record.setStatus(3);
            } else if (record.getStatus() >= 4) {
                record.setStatus(4);
            } else {
                throw SyExceptionUtils.e("状态错误");
            }

            if (record.getStatus().equals(3)) {
                sb.append("(0/1)");
            } else if (record.getStatus() >= 4) {
                sb.append("(X)");
            }

            if (record.getStatus() > 4) {
                record.setStatus(4);
            }

            record.setStatusStr(sb.toString());

            List<PlatePhase> p = platePhaseMap.get(record.getPlateCode());

            Optional<PlatePhase> first = p.stream().filter(e -> e.getPhaseCode().equals("JG") || e.getPhaseCode().equals("HG")).findFirst();
            if (!first.isPresent()) {
//                throw SyExceptionUtils.e("工艺阶段错误");
                continue;
            }
            PlatePhase jgPhase = first.get();
            if (StringUtils.hasText(record.getStationCode())) {
                record.setSplitGroupCode(record.getStationCode());
            } else {
                record.setSplitGroupCode(jgPhase.getGroupCode());
            }
            record.setPlanWorkTime(jgPhase.getWorkTime() == null ? null : new BigDecimal(jgPhase.getWorkTime()));

            Optional<PlatePhase> min = p.stream().filter(e -> e.getPhaseSeq() > jgPhase.getPhaseSeq()).min(Comparator.comparing(PlatePhase::getPhaseSeq));
            if (!min.isPresent()) {
//                throw SyExceptionUtils.e("工艺阶段错误");
                continue;
            }
            record.setNextGroupCode(min.get().getGroupCode());
            if (record.getPlanStartDateTime() != null && record.getActualStartDateTime() != null) {
                LocalDateTime localDateTime = record.getActualStartDateTime().plusSeconds(record.getPlanWorkTime().intValue());
                record.setPlanEndDateTime(localDateTime);
                LocalDateTime now = LocalDateTime.now();
                if (record.getActualFinishDateTime() != null) {
                    now = record.getActualFinishDateTime();
                }
                long secondsBetween = ChronoUnit.SECONDS.between(now, localDateTime);
                record.setRemainingWorkTime(new BigDecimal(secondsBetween));
            }

            if (StringUtils.hasText(record.getPngUrl())) {
                record.setPngUrl(String.format(projectConfig.getUrlPre(), record.getPlateCode() + ".png", record.getPngUrl()));
            }

        }

        return new BaseListResVo<>(page);

    }

    public String findFirstGroup(String workChain, String nextGroupCode) {
        return nextGroupCode.split(",")[0];
    }

    public String findSplitGroup(String workChain, String chainGroupCode) {

        String[] groupSplit = chainGroupCode.split(",");
        String[] workChainSplit = workChain.split("-");
        Integer index = null;
        for (int i = 0; i < workChainSplit.length; i++) {
            if (projectConfig.getCuttingProcess().contains(workChainSplit[i])) {
                index = i;
                break;
            }
        }

        if (index == null) {
            return null;
        }
        return groupSplit[index];
    }

    public BaseListResVo<ReportProPickResVo> proPick(ReportProPickReqVo reqVo) {
        String[] split = reqVo.getId().split("\\$");
        if (!split[0].equals("4")) {
            throw SyExceptionUtils.e("类型不匹配");
        }

        Integer id = Integer.parseInt(split[1]);
        ApsWorkOrder workOrder = apsWorkOrderMapper.selectById(id);
        if (!workOrder.getMaterType().equals("Component")) {
            return BaseListResVo.empty();
        }

        ReportProPickResVo r = new ReportProPickResVo();
        r.setTotalCount(workOrder.getOrderCount());
        r.setFinishCount(workOrder.getFinishCount());
        return new BaseListResVo<>(Lists.newArrayList(r));
    }

    public BaseListResVo<ReportPickNestDrawResVo> pickNest(BaseIdReqVo reqVo) {


        WmsPlatePick pickList = wmsPlatePickMapper.selectById(reqVo.getId());
//        List<Integer> nestPlateIdList = pickList.stream().map(WmsPlatePick::getNestPlateId).collect(Collectors.toList());
        SinoCamReceiveNestPlate nestPlateList = sinoCamReceiveNestPlateMapper.lambdaQuery().eq(SinoCamReceiveNestPlate::getId, pickList.getNestPlateId()).one();

//        List<Integer> collect = nestPlateList.stream().map(SinoCamReceiveNestPlate::getReceiveNestId).distinct().collect(Collectors.toList());
        List<SinoCamReceiveNestPart> partList = sinoCamReceiveNestPartMapper.lambdaQuery().in(SinoCamReceiveNestPart::getReceiveNestId, nestPlateList.getReceiveNestId()).list();

        List<Integer> planIdList = partList.stream().filter(e -> StringUtils.hasText(e.getNestPlanId())).map(e -> Integer.parseInt(e.getNestPlanId())).distinct().collect(Collectors.toList());
        List<ApsWorkDetail> workDetailList = apsWorkDetailMapper.lambdaQuery().in(ApsWorkDetail::getId, planIdList).list();

        Map<Integer, ApsWorkDetail> workDetailMap = workDetailList.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<Integer> orderIdList = workDetailList.stream().map(ApsWorkDetail::getOrderId).distinct().collect(Collectors.toList());
        List<Order> orders = orderMapper.selectBatchIds(orderIdList);
        Map<Integer, Order> orderMap = orders.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));

        List<Integer> apsOrderIdList = workDetailList.stream().map(ApsWorkDetail::getApsOrderId).collect(Collectors.toList());
        List<ApsOrder> apsOrders = apsOrderMapper.selectBatchIds(apsOrderIdList);
        Map<Integer, ApsOrder> apsOrderMap = apsOrders.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity()));


        List<ReportPickNestDrawResVo> collect1 = partList.stream().map(e -> {


            ReportPickNestDrawResVo r = new ReportPickNestDrawResVo();
            r.setId(e.getId());
            r.setPlmId(e.getPartId());
            r.setVersion("1");
            r.setPkgUsedCount(e.getQuantity());
            r.setOrderUsedCount(null);
            r.setOrderCount(null);
            r.setLength(e.getLength());
            r.setWidth(e.getWidth());
            r.setPartMapUrl(String.format(projectConfig.getUrlPre(), e.getPartId(), e.getPartMapUrl()));

            if (!StringUtils.hasText(e.getNestPlanId())) {
                return r;
            }
            ApsWorkDetail apsWorkDetail = workDetailMap.get(Integer.parseInt(e.getNestPlanId()));

            if (apsWorkDetail == null) {
                return r;
            }
            Order order = orderMap.get(apsWorkDetail.getOrderId());

            ApsOrder apsOrder = apsOrderMap.get(apsWorkDetail.getApsOrderId());

            ApsWorkOrder o = apsWorkOrderMapper.selectById(apsWorkDetail.getApsWorkOrderId());

            ApsWorkOrder total = apsWorkOrderMapper.sumCount(o.getBomId());

            OrderPart one = orderPartMapper.lambdaQuery().eq(OrderPart::getPlmId, o.getPlmId()).one();

            r.setWeight(one.getNetWeight());

            r.setSerialCode(order.getSerialCode());
            r.setPkgCode(PkgUtils.gen(apsOrder.getSeq()));
            r.setPkgCount(apsWorkDetail.getTotalCount().intValue());
            r.setOrderCount(total.getOrderCount().intValue());
            r.setOrderUsedCount(total.getFinishCount() == null ? 0 : total.getFinishCount().intValue());
            r.setPlanEndDateTime(apsWorkDetail.getPlanEndDateTime());
            return r;
        }).collect(Collectors.toList());

        return new BaseListResVo<>(collect1);
    }

    public ReportPickDrawResVo pickDraw(ReportPickDrawReqVo reqVo) {
        WmsPlatePick wmsPlatePick = wmsPlatePickMapper.selectById(reqVo.getId());


        return null;
    }

    public ReportProSearchPlmIdResVo proSearchPlmId(ReportProSearchPlmIdReqVo reqVo) {
        LambdaQueryChainWrapper<ApsWorkOrder> wrapper = apsWorkOrderMapper.lambdaQuery();
        if (StringUtils.hasText(reqVo.getPlmId())) {
            wrapper.eq(ApsWorkOrder::getPlmId, reqVo.getPlmId());
        } else if (StringUtils.hasText(reqVo.getWorkOrderCode())) {
            wrapper.eq(ApsWorkOrder::getWorkOrderCode, reqVo.getWorkOrderCode());
        } else {
            throw SyExceptionUtils.e("参数错误");
        }

        if(StringUtils.hasText(reqVo.getConstructCode())){
            List<Order> orderList = orderMapper.lambdaQuery().like(Order::getConstructNo, reqVo.getConstructCode()).list();
            if(CollUtil.isNotEmpty(orderList)){
                wrapper.in(ApsWorkOrder::getOrderId, orderList.stream().map(Order::getId).collect(Collectors.toList()));
            }
        }
        wrapper.in(ApsWorkOrder::getOrderType,1, 3, 4);
        List<ApsWorkOrder> list = wrapper.list();

        if (CollUtil.isEmpty(list)) {
            return new ReportProSearchPlmIdResVo(4);
        }

        String materType = list.get(list.size() - 1).getMaterType();

        Map<String, Integer> typeMap = new HashMap<>();
        typeMap.put("Assembly", 5);
        typeMap.put("Platepart", 6);
        typeMap.put("Component", 7);

        Integer type = typeMap.computeIfAbsent(materType, k -> 4);

        ReportProSearchPlmIdResVo resVo = new ReportProSearchPlmIdResVo();
        resVo.setMaterType(type);

        return resVo;

    }

    public BaseListResVo<ReportProOrderTreeResVo> proLocationPart(ReportProLocaltionPartReqVo reqVo) {
        List<String> type = Arrays.asList("2", "3", "4");

        String[] split = reqVo.getId().split("\\$");
        if (!(type.contains(split[0]))) {
            return BaseListResVo.empty();
        }

        if ("2".contains(split[0])) {
            Integer id = Integer.parseInt(split[1]);

            Order order = orderMapper.selectById(id);
            List<Order> orderList = orderMapper.lambdaQuery()
                    .gt(Order::getCreateDateTime, LocalDateTime.now().minusDays(180).format(DatePattern.NORM_DATETIME_FORMATTER))
                    .eq(Order::getOrderType, order.getOrderType())
                    .list();

            Map<Integer, String> orderType = new HashMap<>();
            orderType.put(1, "1$1");
            orderType.put(4, "11$1");
            orderType.put(3, "21$1");

            List<ReportProOrderTreeResVo> collect = orderList.stream()
                    .map(e -> {
                        ReportProOrderTreeResVo orderRes = new ReportProOrderTreeResVo();
                        orderRes.setStatus(e.getOrderStatus());
                        orderRes.setDeliveryDate(e.getDeliveryDateTime().toLocalDate());
                        orderRes.setName(e.getSerialCode() + "-" + e.getMaterName());
                        orderRes.setTreeType(2);
                        orderRes.setId(orderRes.getTreeType() + "$" + e.getId());
                        orderRes.setPid(orderType.get(e.getOrderType()));
                        if (e.getOrderStatus().equals(8)) {
                            orderRes.setIconCls(2);
                        } else if (e.getOrderStatus().equals(9) || e.getOrderStatus().equals(10)) {
                            orderRes.setIconCls(1);
                        } else {
                            orderRes.setIconCls(3);
                        }
                        orderRes.setFinishCount(new BigDecimal(e.getFinishQty()));
                        orderRes.setTotalCount(new BigDecimal(e.getOrderQty()));
                        orderRes.setUnit("架");
                        return orderRes;
                    })
                    .collect(Collectors.toList());


            ReportProOrderTreeResVo r1 = new ReportProOrderTreeResVo();
            r1.setTreeType(1);
            r1.setId("1$1");
            r1.setName("产品订单");
            r1.setLeaf(false);
            r1.setIconCls(8);

            ReportProOrderTreeResVo r2 = new ReportProOrderTreeResVo();
            r2.setTreeType(11);
            r2.setId("11$1");
            r2.setName("工装订单");
            r2.setLeaf(true);
            r2.setIconCls(9);

            ReportProOrderTreeResVo r3 = new ReportProOrderTreeResVo();
            r3.setTreeType(21);
            r3.setId("21$1");
            r3.setName("外揽订单");
            r3.setLeaf(true);
            r3.setIconCls(10);

            collect.add(r1);
            collect.add(r2);
            collect.add(r3);

            return new BaseListResVo<>(collect);
        }

        Map<Integer, String> map = new HashMap<>();
        map.put(1, "Assembly");
        map.put(2, "Platepart");
        map.put(3, "Component");

        Integer id = Integer.parseInt(split[1]);
        ApsWorkOrder apsWorkOrder = apsWorkOrderMapper.selectById(id);
        ApsOrder apsOrder = apsOrderMapper.selectById(apsWorkOrder.getApsOrderId());
        Order order = orderMapper.selectById(apsOrder.getOrderId());

        List<ApsWorkOrder> workOrderList = apsWorkOrderMapper.lambdaQuery()
                .eq(ApsWorkOrder::getApsOrderId, apsWorkOrder.getApsOrderId())
                .list();


        Map<Integer, ApsWorkOrder> apsWorkOrderMap = workOrderList.stream().collect(Collectors.toMap(ApsWorkOrder::getId, Function.identity()));
        Map<Integer, List<ApsWorkOrder>> workOrderPidMap = workOrderList.stream().filter(e -> e.getPid() != null).collect(Collectors.groupingBy(ApsWorkOrder::getPid));


        ApsWorkOrder current = apsWorkOrder;
        List<ApsWorkOrder> root = new ArrayList<>();
        while (current != null) {
            root.add(current);
            current = apsWorkOrderMap.get(current.getPid());
        }

        if (CollUtil.isNotEmpty(root)) {
            root.remove(0);
        }
        if (CollUtil.isNotEmpty(root)) {
            Collections.reverse(root);
        }

        List<ReportProOrderTreeResVo> all = root.stream()
                .flatMap(e1 -> {
                    List<ApsWorkOrder> apsWorkOrders = workOrderPidMap.get(e1.getId());
                    List<String> collect = apsWorkOrders.stream().map(ApsWorkOrder::getPlmId).distinct().collect(Collectors.toList());
                    List<Part> partList1 = partMapper.lambdaQuery().in(Part::getPlmId, collect).eq(Part::getPhaseCode, WorkshopProp.KJ_PHASE_CODE).eq(Part::getConstructNo, order.getConstructNo()).list();
                    Map<String, Part> partMap1 = partList1.stream().collect(Collectors.toMap(Part::getPlmId, Function.identity()));

                    return apsWorkOrders.stream()
                            .sorted(Comparator.comparing(ApsWorkOrder::getMaterType).thenComparing(ApsWorkOrder::getPlmId).reversed())
                            .map(e -> {
                                ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
                                r.setTreeType(4);
                                r.setId(r.getTreeType() + "$" + e.getId());
                                r.setName(e.getPlmId());
                                if (e.getPid() != null) {
                                    ApsWorkOrder parent = apsWorkOrderMap.get(e.getPid());
                                    r.setPid(r.getTreeType() + "$" + parent.getId());

                                }
                                r.setLeaf(workOrderPidMap.get(e.getId()) == null);
                                r.setDeliveryDate(e.getPlanEndDateTime().toLocalDate());
                                if (e.getWorkChain().equals("WL")) {
                                    r.setIconCls(7);
                                } else {
                                    if (e.getMaterType().equals("Assembly")) {
                                        r.setIconCls(5);
                                    } else if (e.getMaterType().equals("Platepart")){
                                        r.setIconCls(6);
                                    } else {
                                        r.setIconCls(7);
                                    }
                                }

                                Part part = partMap1.get(e.getPlmId());
                                if (part == null) {
                                    r.setInProgressCount(new BigDecimal(0));
                                } else {
                                    r.setInProgressCount(new BigDecimal(part.getPartCount()));
                                }

                                r.setFinishCount(e.getFinishCount());
                                r.setTotalCount(e.getOrderCount());
                                r.setUnit("件");
                                return r;
                            });
                })
                .collect(Collectors.toList());


        List<String> plmIdList1 = workOrderList.stream().map(ApsWorkOrder::getPlmId).distinct().collect(Collectors.toList());
        List<Part> partList1 = partMapper.lambdaQuery().in(Part::getPlmId, plmIdList1).eq(Part::getPhaseCode, WorkshopProp.KJ_PHASE_CODE).eq(Part::getConstructNo, order.getConstructNo()).list();
        Map<String, Part> partMap1 = partList1.stream().collect(Collectors.toMap(Part::getPlmId, Function.identity()));
        List<ReportProOrderTreeResVo> collect = workOrderList.stream()
                .filter(e -> e.getPid() == null)
                .sorted(Comparator.comparing(ApsWorkOrder::getMaterType).thenComparing(ApsWorkOrder::getPlmId).reversed())
                .map(e -> {
                    ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
                    r.setTreeType(4);
                    r.setId(r.getTreeType() + "$" + e.getId());
                    r.setName(e.getPlmId());

                    r.setPid("3$" + apsOrder.getId());

                    r.setLeaf(workOrderPidMap.get(e.getId()) == null);
                    if(e.getPlanEndDateTime() != null){
                        r.setDeliveryDate(e.getPlanEndDateTime().toLocalDate());
                    }
                    if (e.getWorkChain().equals("WL")) {
                        r.setIconCls(7);
                    } else {
                        if (e.getMaterType().equals("Assembly")) {
                            r.setIconCls(5);
                        } else if (e.getMaterType().equals("Platepart")){
                            r.setIconCls(6);
                        } else {
                            r.setIconCls(7);
                        }
                    }

                    Part part = partMap1.get(e.getPlmId());
                    if (part == null) {
                        r.setInProgressCount(new BigDecimal(0));
                    } else {
                        r.setInProgressCount(new BigDecimal(part.getPartCount()));
                    }
                    r.setFinishCount(e.getFinishCount());
                    r.setTotalCount(e.getOrderCount());
                    r.setUnit("件");
                    return r;
                })
                .collect(Collectors.toList());

        collect.addAll(all);

        ReportProOrderTreeResVo orderRes = new ReportProOrderTreeResVo();
        orderRes.setStatus(order.getOrderStatus());
        orderRes.setDeliveryDate(order.getDeliveryDateTime().toLocalDate());
        orderRes.setName(order.getSerialCode() + "-" + order.getMaterName());
        orderRes.setTreeType(2);
        orderRes.setId(orderRes.getTreeType() + "$" + order.getId());
        orderRes.setPid("1$1");
        if (order.getOrderStatus().equals(8)) {
            orderRes.setIconCls(2);
        } else if (order.getOrderStatus().equals(9)) {
            orderRes.setIconCls(1);
        } else {
            orderRes.setIconCls(3);
        }
        orderRes.setFinishCount(new BigDecimal(order.getFinishQty()));
        orderRes.setTotalCount(new BigDecimal(order.getOrderQty()));
        orderRes.setUnit("架");

        List<ApsOrder> apsOrderList = apsOrderMapper.lambdaQuery().eq(ApsOrder::getOrderId, order.getId()).list();
        List<ReportProOrderTreeResVo> pkgList = apsOrderList.stream()
                .sorted(Comparator.comparingInt(ApsOrder::getSeq))
                .map(e -> {
                    ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
                    r.setTreeType(3);
                    r.setId(r.getTreeType() + "$" + e.getId());
                    r.setName(PkgUtils.gen(e.getSeq()));
                    r.setPid("2" + "$" + e.getOrderId());
                    r.setDeliveryDate(e.getPlanEndDateTime().toLocalDate());
                    r.setIconCls(4);
                    r.setFinishCount(new BigDecimal(e.getFinishQty()));
                    r.setTotalCount(new BigDecimal(e.getOrderQty()));
                    r.setUnit("架");
                    return r;
                })
                .collect(Collectors.toList());


        List<ReportProOrderTreeResVo> topType = new ArrayList<>();

        ReportProOrderTreeResVo r1 = new ReportProOrderTreeResVo();
        r1.setTreeType(1);
        r1.setId("1$1");
        r1.setName("产品订单");
        r1.setLeaf(false);
        r1.setIconCls(8);

        ReportProOrderTreeResVo r2 = new ReportProOrderTreeResVo();
        r2.setTreeType(1);
        r2.setId("1$2");
        r2.setName("工装订单");
        r2.setLeaf(true);
        r2.setIconCls(9);

        ReportProOrderTreeResVo r3 = new ReportProOrderTreeResVo();
        r3.setTreeType(1);
        r3.setId("1$3");
        r3.setName("物料订单");
        r3.setLeaf(true);
        r3.setIconCls(10);
        topType.add(r1);
        topType.add(r2);
        topType.add(r3);

        topType.add(orderRes);

        topType.addAll(pkgList);

        topType.addAll(collect);

//        List<ReportProOrderTreeResVo> collect = workOrderList.stream()
//                .sorted(Comparator.comparing(ApsWorkOrder::getMaterType).thenComparing(ApsWorkOrder::getPlmId).reversed())
//                .map(e -> {
//                    ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
//                    r.setTreeType(4);
//                    r.setId(r.getTreeType() + "$" + e.getId());
//                    r.setName(e.getPlmId());
//
//                    ApsWorkOrder parent = apsWorkDetailMap.get(e.getId());
//                    if (parent == null) {
//                        r.setPid(r.getTreeType() + "$" + parent.getId());
//                    }
//
//                    r.setLeaf(map.get(e.getId()) == null);
//                    r.setDeliveryDate(e.getPlanEndDateTime().toLocalDate());
//                    if(e.getWorkChain().equals("WL")){
//                        r.setIconCls(7);
//                    } else {
//                        if (r.isLeaf()) {
//                            r.setIconCls(6);
//                        } else {
//                            r.setIconCls(5);
//                        }
//                    }
//                    r.setFinishCount(e.getFinishCount());
//                    r.setTotalCount(e.getOrderCount());
//                    r.setUnit("件");
//                    return r;
//                })
//                .collect(Collectors.toList());

        return new BaseListResVo<>(topType);
    }

    public BasePageResVo<ReportProductionNestPhaseResVo> productionNestPhase(BaseIdReqVo reqVo) {

        SinoCamReceiveNestNest nestReceiveNest = sinoCamReceiveNestNestMapper.selectById(reqVo.getId());
        List<SinoCamReceiveNestPlate> plateList = sinoCamReceiveNestPlateMapper.lambdaQuery().in(SinoCamReceiveNestPlate::getReceiveNestId, nestReceiveNest.getReceiveNestId()).list();

        List<ReportProductionNestPhaseResVo> resList = new ArrayList<>();

        for (SinoCamReceiveNestPlate nestReceivePlate : plateList) {
            WmsPlatePick platePick = wmsPlatePickMapper.lambdaQuery().eq(WmsPlatePick::getMaterialId, nestReceivePlate.getStockListNo()).one();
            /*
            ReportProductionNestPhaseResVo resVo = new ReportProductionNestPhaseResVo();
            resVo.setPhaseCode(WorkshopProp.LL_PHASE_CODE);
            resVo.setPhaseName(WorkshopProp.LL_PHASE_NAME);
            resVo.setGroupCode(WorkshopProp.LL_GROUP);
            resVo.setTotalCount(1);
            if (platePick.getPlateState() >= 4) {
                resVo.setFinishCount(1);
                resVo.setFailCount(0);
            } else {
                resVo.setFinishCount(0);
                resVo.setFailCount(0);
            }
            resVo.setFinishDateTime(platePick.getOutTime());

            resList.add(resVo);
             */

            List<WorkDetailTask> list = workDetailTaskMapper.lambdaQuery()
                    .eq(WorkDetailTask::getMaterCode, platePick.getMaterialId())
                    .eq(WorkDetailTask::getType, 1)
                    .list();

            List<ApsWorkDetail> list1 = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getType, 1).eq(ApsWorkDetail::getMaterNo, platePick.getMaterialId()).list();
            Map<String, ApsWorkDetail> collect1 = list1.stream().collect(Collectors.toMap(e -> e.getPhaseCode(), Function.identity()));

            Map<String, WorkDetailTask> phaseMap = list.stream().collect(Collectors.toMap(WorkDetailTask::getPhaseCode, Function.identity()));

            Plate plate = plateMapper.lambdaQuery().eq(Plate::getMaterCode, platePick.getMaterialId()).one();

            List<PlatePhase> phaseList = platePhaseMapper.lambdaQuery()
                    .eq(PlatePhase::getPlateCode, plate.getMaterCode())
                    .orderByAsc(PlatePhase::getPhaseSeq)
                    .list();

            List<ReportProductionNestPhaseResVo> collect = phaseList.stream()
                    .map(e -> {
                        ReportProductionNestPhaseResVo r = new ReportProductionNestPhaseResVo();
                        r.setPlateCode(e.getPlateCode());
                        r.setPhaseCode(e.getPhaseCode());
                        r.setPhaseName(e.getPhaseName());
                        r.setGroupCode(e.getGroupCode());
                        r.setTotalCount(1);
                        r.setFinishCount(0);
                        r.setFailCount(0);
                        if (e.getWorkTime() != null) {
                            r.setWorkTime(new BigDecimal(e.getWorkTime()));
                        }

                        ApsWorkDetail apsWorkDetail = collect1.get(e.getPhaseCode());
                        if (apsWorkDetail != null) {
                            r.setPlanStartDateTime(apsWorkDetail.getPlanStartDateTime());
                            r.setPlanEndDateTime(apsWorkDetail.getPlanEndDateTime());
                        }


                        WorkDetailTask task = phaseMap.get(e.getPhaseCode());
                        if (task != null) {
                            if (task.getFinishCount() != null) {
                                r.setFinishCount(task.getFinishCount());
                            }
                            if (task.getFailCount() != null) {
                                r.setFailCount(task.getFailCount());
                            }
                            r.setFinishDateTime(task.getActualEndDateTime());
                        }

                        return r;

                    })
                    .collect(Collectors.toList());

            resList.addAll(collect);
        }

        resList = resList.stream().filter(e -> !e.getPhaseCode().equals(WorkshopProp.FJ_PHASE_CODE)).collect(Collectors.toList());

        for (ReportProductionNestPhaseResVo r : resList) {
            if (r.getPhaseCode().equals(WorkshopProp.LL_PHASE_CODE)) {
                r.setWorkTime(new BigDecimal(5 * 60));
            } else if (r.getPhaseCode().equals(WorkshopProp.YC_PHASE_CODE)) {
                r.setWorkTime(new BigDecimal(8 * 60));
            }

            if (r.getWorkTime() != null) {
                r.setWorkTime(r.getWorkTime().divide(new BigDecimal(60), 2, RoundingMode.HALF_UP));
            }
        }


        return new BasePageResVo<>(resList.size(), resList);
    }

    public BaseListResVo<ReportProOrderTreeResVo> proExpandTree(ReportProExpandTreeReqVo reqVo) {

        String[] split = reqVo.getId().split("\\$");
        if (!(split[0].equals("4") || split[0].equals("3"))) {
            return BaseListResVo.empty();
        }

        Integer id = Integer.parseInt(split[1]);
        ApsWorkOrder apsWorkOrder = apsWorkOrderMapper.selectById(id);
        Order o = orderMapper.selectById(apsWorkOrder.getOrderId());

        List<ApsWorkOrder> workOrderList = apsWorkOrderMapper.lambdaQuery()
                .eq(ApsWorkOrder::getApsOrderId, apsWorkOrder.getApsOrderId())
                .list();
        Map<Integer, List<ApsWorkOrder>> workOrderPidMap = workOrderList.stream().filter(e -> e.getPid() != null).collect(Collectors.groupingBy(ApsWorkOrder::getPid));

        List<String> plmIdList = workOrderList.stream().map(e -> e.getPlmId()).distinct().collect(Collectors.toList());
        if (CollUtil.isEmpty(plmIdList)) {
            return BaseListResVo.empty();
        }
        List<Part> list = partMapper.lambdaQuery().in(Part::getPlmId, plmIdList).eq(Part::getConstructNo, o.getConstructNo()).eq(Part::getPhaseCode, WorkshopProp.KJ_PHASE_CODE).list();
        Map<String, Part> partMap = list.stream().collect(Collectors.toMap(e -> e.getPlmId(), Function.identity(), (e1, e2) -> {
            e1.setDamageCount(e1.getDamageCount() + e2.getDamageCount());
            e1.setFailCount(e1.getFailCount() + e2.getFailCount());
            e1.setPartCount(e1.getPartCount() + e2.getPartCount());
            return e1;
        }));

        List<ReportProOrderTreeResVo> collect = workOrderList.stream()
                .sorted(Comparator.comparing(ApsWorkOrder::getLevel).reversed().thenComparing(ApsWorkOrder::getMaterType).thenComparing(ApsWorkOrder::getPlmId).reversed())
                .map(e -> {
                    ReportProOrderTreeResVo r = new ReportProOrderTreeResVo();
                    r.setTreeType(4);
                    r.setId(r.getTreeType() + "$" + e.getId());
                    r.setName(e.getPlmId());

                    if (e.getPid() == null) {
                        r.setPid("3$" + e.getApsOrderId());
                    } else {
                        r.setPid(r.getTreeType() + "$" + e.getPid());
                    }

                    r.setLeaf(workOrderPidMap.get(e.getId()) == null);
                    if(e.getPlanEndDateTime() != null){
                        r.setDeliveryDate(e.getPlanEndDateTime().toLocalDate());
                    }
                    if (e.getWorkChain().equals("WL")) {
                        r.setIconCls(7);
                    } else {
                        if (e.getMaterType().equals("Assembly")) {
                            r.setIconCls(5);
                        } else if (e.getMaterType().equals("Platepart")){
                            r.setIconCls(6);
                        } else {
                            r.setIconCls(7);
                        }
                    }

                    Part part = partMap.get(e.getPlmId());
                    if (part == null) {
                        r.setInProgressCount(new BigDecimal(0));
                    } else {
                        r.setInProgressCount(new BigDecimal(part.getPartCount()));
                    }
                    r.setFinishCount(e.getFinishCount());
                    r.setTotalCount(e.getOrderCount());
                    r.setUnit("件");
                    return r;
                })
                .collect(Collectors.toList());


        return new BaseListResVo<>(collect);
    }

    public BaseListResVo<ReportWorkPlaceCutResVo> plateCutReport(ReportWorkPlaceCutReqVo reqVo) {
        List<ReportWorkPlaceCutResVo> resVo = new ArrayList<>();
        QueryWrapper<WorkRecord> qw = Wrappers.query();
        qw.eq("r.type", 1);
        qw.eq("r.work_type", 2);
        if (reqVo.getStartDate() != null) {
            qw.ge("r.work_time", reqVo.getStartDate() + " 06:00:00");
        } // 查询当天 6 点之后的时间
        if (reqVo.getEndDate() != null) {
            qw.lt("r.work_time", reqVo.getEndDate() + " 06:00:00");
        } // 查询第二天的 6 点 之前的时间（例如，只看一天的数据，输入两个时间应该相同）
        String groupCode = "";
        if (reqVo.getCutMachineType() == 1) {
            groupCode = "1-1_HYQG_00";
        }
        if (reqVo.getCutMachineType() == 2) {
            groupCode = "1-2_JGQG_00";
        }
        if (reqVo.getCutMachineType() == 3) {
            groupCode = "1-3_JGQG_00";
        }
        qw.eq("r.group_number", groupCode);
        if (StringUtils.hasText(reqVo.getNestId())) {
            qw.like("p.nest_id", reqVo.getNestId());
        }
        if (reqVo.getSort() != null && reqVo.getSort() == 1) {
            qw.orderByAsc("r.work_time");
        } else if (reqVo.getSort() != null && reqVo.getSort() == 2) {
            qw.orderByDesc("r.work_time");
        }
        qw.eq("nm.move_type", 1);
        List<ReportWorkStationCutResVo> plateList = workRecordMapper.plateCutReport(qw);
        if (CollUtil.isEmpty(plateList)) {
            return BaseListResVo.of(resVo, ReportWorkPlaceCutResVo.class);
        }
        for (ReportWorkStationCutResVo vo : plateList) {
            vo.setCutTotalWeight(vo.getCutTotalWeight().setScale(2, RoundingMode.HALF_UP));
            vo.setPlateTotalWeight(vo.getPlateTotalWeight().setScale(2, RoundingMode.HALF_UP));
            vo.setRate(vo.getRate().setScale(2, RoundingMode.HALF_UP));
            vo.setTotalTime(vo.getTotalTime().divide(new BigDecimal(60), 2, RoundingMode.UP));
            vo.setWorkTime(vo.getWorkTime().divide(new BigDecimal(60), 2, RoundingMode.UP));
            vo.setCutTotalLength(vo.getCutTotalLength().setScale(2, RoundingMode.HALF_UP));
            vo.setLength(vo.getLength().setScale(2, RoundingMode.HALF_UP));
            vo.setWidth(vo.getWidth().setScale(2, RoundingMode.HALF_UP));
            vo.setThickness(vo.getThickness().setScale(0, RoundingMode.HALF_UP));
            vo.setStandards(vo.getTexture() + "*" + vo.getThickness() + "*" + vo.getLength() + "*" + vo.getWidth());
        }
        Map<String, List<ReportWorkStationCutResVo>> plateMap = plateList.stream().collect(Collectors.groupingBy(ReportWorkStationCutResVo::getStationCode));
        ReportWorkPlaceCutResVo resVoTotal = new ReportWorkPlaceCutResVo();
        resVoTotal.setWorkPlaceName(plateList.get(0).getGroupNumber());
        resVoTotal.setCount(plateList.size());
        // 计算totalTime字段总和
        BigDecimal totalTime = plateList.stream().map(ReportWorkStationCutResVo::getTotalTime).reduce(BigDecimal.ZERO, BigDecimal::add);
        resVoTotal.setTotalWorkTime(totalTime.setScale(2, RoundingMode.HALF_UP));
        // 计算workTime字段总和
        BigDecimal workTime = plateList.stream().map(ReportWorkStationCutResVo::getWorkTime).reduce(BigDecimal.ZERO, BigDecimal::add);
        resVoTotal.setWorkTime(workTime.setScale(2, RoundingMode.HALF_UP));
        // 计算板材吨重
        BigDecimal plateTotalWeight = plateList.stream().map(ReportWorkStationCutResVo::getPlateTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
        resVoTotal.setPlateTotalWeight(plateTotalWeight.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
        // 计算切割净重
        BigDecimal cutTotalWeight = plateList.stream().map(ReportWorkStationCutResVo::getCutTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
        resVoTotal.setCutTotalWeight(cutTotalWeight.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
        // 计算有效切割长度
        BigDecimal cutTotalLength = plateList.stream().map(ReportWorkStationCutResVo::getCutTotalLength).reduce(BigDecimal.ZERO, BigDecimal::add);
        resVoTotal.setCutTotalLength(cutTotalLength.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
        // 产能利用率（未知）
        resVoTotal.setRate(CutUseRateUtils.getCutUseRate(plateList, 0));
        resVoTotal.setPlateListVo(plateList);
        resVo.add(resVoTotal);

        for (String string : plateMap.keySet()) {
            ReportWorkPlaceCutResVo vo = new ReportWorkPlaceCutResVo();
            List<ReportWorkStationCutResVo> plateStationList = plateMap.get(string);
            vo.setWorkPlaceName(string);
            vo.setCount(plateStationList.size());
            // 计算totalTime字段总和
            BigDecimal totalTimeS = plateStationList.stream().map(ReportWorkStationCutResVo::getTotalTime).reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setTotalWorkTime(totalTimeS.setScale(2, RoundingMode.HALF_UP));
            // 计算workTime字段总和
            BigDecimal workTimeS = plateStationList.stream().map(ReportWorkStationCutResVo::getWorkTime).reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setWorkTime(workTimeS.setScale(2, RoundingMode.HALF_UP));
            // 计算板材吨重
            BigDecimal plateTotalWeightS = plateStationList.stream().map(ReportWorkStationCutResVo::getPlateTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setPlateTotalWeight(plateTotalWeightS.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
            // 计算切割净重
            BigDecimal cutTotalWeightS = plateStationList.stream().map(ReportWorkStationCutResVo::getCutTotalWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setCutTotalWeight(cutTotalWeightS.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
            // 计算有效切割长度
            BigDecimal cutTotalLengthS = plateStationList.stream().map(ReportWorkStationCutResVo::getCutTotalLength).reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setCutTotalLength(cutTotalLengthS.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
            // 产能利用率（未知）
            vo.setRate(CutUseRateUtils.getCutUseRate(plateStationList, 1));
            vo.setPlateListVo(plateStationList);
            resVo.add(vo);
        }

        return BaseListResVo.of(resVo, ReportWorkPlaceCutResVo.class);
    }

    public BasePageResVo<ReportWorkPlaceSortResVo> plateSortReport(ReportWorkPlaceSortReqVo reqVo) {
        QueryWrapper<WorkRecord> qw = Wrappers.query();
        qw.eq("r.type", 2);
        qw.eq("r.work_type", 2);
        qw.eq("r.phase_code", "FJ");
        qw.isNotNull("r.station_code");
        qw.isNotNull("r.attr");
        if (reqVo.getStartDate() != null) {
            qw.ge("r.work_time", reqVo.getStartDate() + " 00:00:00");
        }
        if (reqVo.getEndDate() != null) {
            qw.le("r.work_time", reqVo.getEndDate() + " 23:59:59");
        }
        if (!CollUtil.isEmpty(reqVo.getWorkPlace())) {
            qw.in("r.group_number", reqVo.getWorkPlace());
        }
        if (StringUtils.hasText(reqVo.getNestId())) {
            qw.like("p.nest_id", reqVo.getNestId());
        }
        if (StringUtils.hasText(reqVo.getPlateCode())) {
            qw.like("r.attr", reqVo.getPlateCode());
        }
        Page<ReportWorkPlaceSortResVo> page = workRecordMapper.plateSortReport(reqVo.toPage(), qw);

        return BasePageResVo.of(page, ReportWorkPlaceSortResVo.class);
    }

    public BasePageResVo<ReportWorkPlaceSortPartResVo> plateSortPart(ReportWorkPlaceSortPartReqVo reqVo) {
        QueryWrapper<WorkRecord> qw = Wrappers.query();
        qw.eq("r.type", 2);
        qw.eq("r.work_type", 2);
        qw.eq("r.attr", reqVo.getPlateCode());
        qw.eq("r.phase_code", "FJ");
        Page<ReportWorkPlaceSortPartResVo> page = workRecordMapper.plateSortPart(reqVo.toPage(), qw);

        return BasePageResVo.of(page, ReportWorkPlaceSortPartResVo.class);
    }

    public BaseListResVo<ReportProPreResVo> proPre(ReportProPreReqVo reqVo) {

        System.out.println("reqVo = " + reqVo.getId());
        String[] split = reqVo.getId().split("\\$");
        if (!(split[0].equals("4"))) {
            return BaseListResVo.empty();
        }
        Integer id = Integer.parseInt(split[1]);
        ApsWorkOrder apsWorkOrder = apsWorkOrderMapper.selectById(id);
        if (apsWorkOrder == null || !apsWorkOrder.getMaterType().equals("Platepart")) {
            return BaseListResVo.empty();
        }

        List<ReportProPreResVo> resVo = new ArrayList<>();
        // 几何图导入
        ReportProPreResVo importPhase = new ReportProPreResVo();
        importPhase.setPhaseName("几何图导入");
        importPhase.setPhaseCode("import");
        importPhase.setPhaseSeq(1);
        importPhase.setOrderCount(new BigDecimal(1));
//        String code = apsWorkOrder.getPlmId();
//        if (code.endsWith("_170")) {
//            code = code.substring(0, apsWorkOrder.getPlmId().indexOf("_170"));
//        }
//        ImportMbdDxf mbdDxf = importMbdDxfMapper.lambdaQuery().eq(ImportMbdDxf::getPlmid, code).one();

        OrderPart orderPart = orderPartMapper.lambdaQuery().eq(OrderPart::getPlmId, apsWorkOrder.getPlmId()).one();
        if (orderPart == null) {
            importPhase.setFinishCount(new BigDecimal(0));
        } else {
            importPhase.setFinishCount(new BigDecimal(1));
            importPhase.setActualEndDateTime(orderPart.getDrawUpdateTime());
        }


        resVo.add(importPhase);

        // 套料
        ReportProPreResVo taoliaoPhase = new ReportProPreResVo();
        taoliaoPhase.setPhaseName("套料");
        taoliaoPhase.setPhaseCode("nest");
        taoliaoPhase.setPhaseSeq(2);
        taoliaoPhase.setOrderCount(apsWorkOrder.getOrderCount());

        List<ApsWorkDetail> list = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getApsWorkOrderId, apsWorkOrder.getId()).list();
        Optional<ApsWorkDetail> first = list.stream().filter(e -> e.getPhaseCode().equals("JG") || e.getPhaseCode().equals("HG")).findFirst();
        if (first.isPresent()) {
            ApsWorkDetail apsWorkDetail = first.get();
            List<SinoCamReceiveNestPart> list1 = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getNestPlanId, apsWorkDetail.getId()).list();
            if (CollUtil.isEmpty(list1)) {
                taoliaoPhase.setFinishCount(new BigDecimal(0));
            } else {
                IntSummaryStatistics collect = list1.stream().collect(Collectors.summarizingInt(SinoCamReceiveNestPart::getQuantity));
                taoliaoPhase.setFinishCount(new BigDecimal(collect.getSum()));
                taoliaoPhase.setActualEndDateTime(apsWorkDetail.getActualEndDateTime());
            }
        } else {
            taoliaoPhase.setFinishCount(new BigDecimal(0));
        }


        resVo.add(taoliaoPhase);

        return new BaseListResVo<>(resVo);
    }


    public BaseListResVo<ReportNestPartToolResVo> nestPartTool(ReportNestPartToolReqVo reqVo) {
        return null;
    }

    public BaseListResVo<ReportPreNestResVo> preNestReport(ReportPreNestReqVo reqVo) {
        QueryWrapper<LantekNestPlate> qw = Wrappers.query();
        qw.ge("o.order_status", 6);
        if (StringUtils.hasText(reqVo.getConstructCode())) {
            qw.like("o.mater_code", reqVo.getConstructCode());
        }
        if (StringUtils.hasText(reqVo.getTexture())) {
            qw.eq("plate.texture", reqVo.getTexture());
        }
        if (reqVo.getThickness() != null) {
            qw.eq("plate.norm", reqVo.getThickness());
        }
        if (!CollUtil.isEmpty(reqVo.getWorkGroup())) {
            qw.in("nest.split_group_code", reqVo.getWorkGroup());
        }
        if (StringUtils.hasText(reqVo.getVersionCode())) {
            qw.eq("plate.pre_version", reqVo.getVersionCode());
        }
        qw.groupBy(" o.mater_code, plate.texture, plate.norm, nest.split_group_code, plate.pre_version ");
        qw.orderByAsc(" o.mater_code, plate.pre_version, plate.texture, plate.norm ");
        List<ReportPreNestResVo> listVo = lantekNestPlateMapper.preNestReport(qw);

//        Map<String, PlatePreNestStockVo> stockVoMap = apsWmsApiClient.preNestPlateStock();

        if (listVo.size() != 0) {
            for (ReportPreNestResVo resVo : listVo) {
                if (resVo.getStandardPlateLength() == null) {
                    resVo.setStandardPlateLength(String.valueOf(10000));
                }
                if (resVo.getStandardPlateWidth() == null) {
                    resVo.setStandardPlateWidth(String.valueOf(2500));
                }
//                PlatePreNestStockVo stockVo = stockVoMap.get(resVo.getTexture() + "δ" + resVo.getThickness());
//                if (stockVo == null) {
//                    stockVo = new PlatePreNestStockVo();
//                    stockVo.setAmount(0);
//                    stockVo.setWeight(BigDecimal.ZERO);
//                }
                PlatePreNestStockVo stockVo = new PlatePreNestStockVo();
                stockVo.setAmount(0);
                stockVo.setWeight(BigDecimal.ZERO);

                resVo.setStandardPlate(resVo.getStandardPlateLength() + "*" + resVo.getStandardPlateWidth());
                resVo.setRealAmount(stockVo.getAmount());
                resVo.setBuyAmount(stockVo.getAmount() - resVo.getPlanAmount());
                BigDecimal planPlateWeight = new BigDecimal(resVo.getStandardPlateLength()).multiply(new BigDecimal(resVo.getStandardPlateWidth())).multiply(resVo.getThickness()).multiply(BigDecimal.valueOf(7.85)).multiply(new BigDecimal(resVo.getPlanAmount())).divide(new BigDecimal(1000000), 2, RoundingMode.HALF_UP);
                resVo.setPlanPlateWeight(planPlateWeight.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
                resVo.setUsedPlateWeight(resVo.getUsedPlateWeight() != null ? planPlateWeight.subtract(resVo.getUsedPlateWeight()) : planPlateWeight);
                BigDecimal realPlateWeight = stockVo.getWeight();
                resVo.setRealPlateWeight(realPlateWeight.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
                BigDecimal partWeight = resVo.getPartWeight();
                resVo.setBuyPlateWeight(resVo.getRealPlateWeight().subtract(resVo.getPlanPlateWeight()));
                resVo.setRate(partWeight.divide(resVo.getUsedPlateWeight(), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
                resVo.setPartWeight(partWeight.setScale(2, RoundingMode.HALF_UP));
                resVo.setPartArea(resVo.getPartArea().setScale(2, RoundingMode.HALF_UP));
                resVo.setRectangleArea(resVo.getRectangleArea().setScale(2, RoundingMode.HALF_UP));
            }
        }
        return BaseListResVo.of(listVo, ReportPreNestResVo.class);
    }

    public BaseListResVo<ReportPreNestNewResVo> preNestReportNew(ReportPreNestNewReqVo reqVo) {
        QueryWrapper<LantekPushPackage> qw = Wrappers.query();
        if (StringUtils.hasText(reqVo.getPreNestCode())) {
            qw.like("pp.pre_nest_code", reqVo.getPreNestCode());
        }
        if (CollUtil.isNotEmpty(reqVo.getMaterCodeList())) {
            qw.in("pp.plm_id", reqVo.getMaterCodeList());
        }
        if (CollUtil.isNotEmpty(reqVo.getMaterTypeList())) {
            List<String> list = materTypelist(reqVo.getMaterTypeList());

            if (CollUtil.isNotEmpty(list) && StringUtils.hasText(list.get(0))) {
                qw.and(wp -> {
                    int i = 0;
                    wp.like("pp.mater_name", list.get(i));
                    i++;
                    for (; i < list.size(); i++) {
                        wp.or().like("pp.mater_name", list.get(i));
                    }
                });
            }
        }
        if (CollUtil.isNotEmpty(reqVo.getTexture())) {
            qw.in("npl.texture", reqVo.getTexture());
        }
        if (CollUtil.isNotEmpty(reqVo.getThickness())) {
            qw.in("npl.norm", reqVo.getThickness());
        }
        if (!StringUtils.hasText(reqVo.getPreNestCode()) && CollUtil.isEmpty(reqVo.getMaterCodeList()) && CollUtil.isEmpty(reqVo.getMaterTypeList()) && CollUtil.isEmpty(reqVo.getTexture()) && CollUtil.isEmpty(reqVo.getThickness())) {
            qw.ge("pp.create_date_time", LocalDateTime.now().minusDays(7));
        }
//        qw.isNotNull("npa.id");
        qw.groupBy(" pp.pre_nest_code, ppl.plate_length, ppl.plate_width, npl.texture, npl.norm, ps.plate_rate");
        List<ReportPreNestInfoNewResVo> infoVoList = lantekPushPackageMapper.preNestReport(qw);

        if (CollUtil.isEmpty(infoVoList)) {
            return BaseListResVo.empty();
        }

        List<LantekPushPackage> comPkgList = lantekPushPackageMapper.lambdaQuery().in(LantekPushPackage::getPreNestCode, infoVoList.stream().map(ReportPreNestInfoNewResVo::getPreNestCode).distinct().collect(Collectors.toList())).list();
        Map<String, List<LantekPushPackage>> comPkgMap = comPkgList.stream().collect(Collectors.groupingBy(LantekPushPackage::getPreNestCode));

        Map<String, List<ReportPreNestInfoNewResVo>> infoVoMap = infoVoList.stream().collect(Collectors.groupingBy(ReportPreNestInfoNewResVo::getPreNestCode));
        Set<String> preNestCodeSet = infoVoMap.keySet();
        List<String> preNestCodeList = preNestCodeSet.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());

        List<ReportPreNestNewResVo> resVoList = new ArrayList<>();
        for (String preNestCode : preNestCodeList) {

            QueryWrapper<LantekNestExcess> qwe = new QueryWrapper<>();
            qwe.like("nest_id", preNestCode);
            qwe.groupBy(" e.texture, e.norm");
            List<ReportPreExcessWeightVo> preExcessWeightList = lantekNestExcessMapper.getPreExcessWeight(qwe);
            Map<String, ReportPreExcessWeightVo> preExcessWeightMap = new HashMap<>();
            if (CollUtil.isNotEmpty(preExcessWeightList)) {
                preExcessWeightMap = preExcessWeightList.stream().collect(Collectors.toMap(ReportPreExcessWeightVo::getNorm, Function.identity()));
            }

            ReportPreNestNewResVo resVo = new ReportPreNestNewResVo();
            List<ReportPreNestInfoNewResVo> infoList = infoVoMap.get(preNestCode);

            List<LantekPushPackage> pkgMaterList = comPkgMap.get(preNestCode);
            List<String> materCodeList = pkgMaterList.stream().map(e -> {
                String materCode = "";
                materCode = e.getPlmId() + "（" + e.getOrderCount() + "架）";
                return materCode;
            }).collect(Collectors.toList());
            List<String> materTypeList = pkgMaterList.stream().map(e -> {
                String materType = "";
                materType = materType(e.getPlmId());
                return materType;
            }).collect(Collectors.toList());

            for (ReportPreNestInfoNewResVo infoVo : infoList) {
                ReportPreExcessWeightVo preExcessWeightVo = preExcessWeightMap.get(infoVo.getTexture() + "#" + infoVo.getThickness());

                infoVo.setStandardPlate(infoVo.getStandardPlateLength() + "*" + infoVo.getStandardPlateWidth());
                if (ObjectUtils.isNotEmpty(infoVo.getPlanAmount()) && ObjectUtils.isNotEmpty(infoVo.getThickness())) {
                    BigDecimal planPlateWeight = new BigDecimal(infoVo.getStandardPlateLength()).multiply(new BigDecimal(infoVo.getStandardPlateWidth())).multiply(infoVo.getThickness()).multiply(BigDecimal.valueOf(7.85)).multiply(new BigDecimal(infoVo.getPlanAmount())).divide(new BigDecimal(1000000), 2, RoundingMode.HALF_UP);
                    infoVo.setPlanPlateWeight(planPlateWeight.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
                    infoVo.setUsedPlateWeight(ObjectUtils.isNotEmpty(preExcessWeightVo) ? planPlateWeight.subtract(preExcessWeightVo.getWeight()) : planPlateWeight);
                } else {
                    infoVo.setPlanPlateWeight(BigDecimal.ZERO);
                    infoVo.setUsedPlateWeight(BigDecimal.ZERO);
                }
                BigDecimal partWeight = infoVo.getPartWeight();
                // infoVo.setRate(partWeight.divide(infoVo.getUsedPlateWeight(), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
                infoVo.setRate(ObjectUtils.isNotEmpty(infoVo.getRate()) ? infoVo.getRate().setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO);
                infoVo.setPartWeight(ObjectUtils.isNotEmpty(infoVo.getPartWeight()) ? partWeight.setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO);
            }
            resVo.setPreNestCode(preNestCode);
            resVo.setMaterCodeList(materCodeList.stream().distinct().collect(Collectors.toList()));
            resVo.setMaterTypeList(materTypeList.stream().distinct().collect(Collectors.toList()));
            resVo.setInfoList(infoList);
            resVoList.add(resVo);
        }
        return BaseListResVo.of(resVoList, ReportPreNestNewResVo.class);
    }

    public String materType(String s) {
        if (s.contains("0101P")) {
            return "顶梁";
        } else if (s.contains("0201P")) {
            return "掩护梁";
        } else if (s.contains("0301P")) {
            return "底座";
        } else {
            return "侧板";
        }
    }

    public List<String> materTypelist(List<String> materNameList) {
        List<String> nameList = new ArrayList<>();
        if (materNameList.contains("1")) {
            nameList.add("顶梁");
        }
        if (materNameList.contains("2")) {
            nameList.add("掩护梁");
        }
        if (materNameList.contains("3")) {
            nameList.add("底座");
        }
        if (materNameList.contains("4")) {
            nameList.add("侧板");
        }
        if (materNameList.contains("5")) {
            nameList.add("连杆");
        }
        return nameList;
    }

    public BaseListResVo<ReportPreNestErrResVo> preNestException(ReportPreNestErrReqVo reqVo) {
        QueryWrapper<LantekPushPackage> qw = new QueryWrapper<>();
        qw.eq("pp.pre_nest_code", reqVo.getPreNestCode());
        qw.eq("d.status", 5);
        if (StringUtils.hasText(reqVo.getParPlmId())) {
            qw.like("p.component_id", reqVo.getParPlmId());
        }
        if (StringUtils.hasText(reqVo.getPlmId())) {
            qw.like("p.part_id", reqVo.getPlmId());
        }
        if (StringUtils.hasText(reqVo.getMaterName())) {
            qw.like("p.part_name", reqVo.getMaterName());
        }
        if (StringUtils.hasText(reqVo.getErrInfo())) {
            qw.like("d.error_msg", reqVo.getErrInfo());
        }
        qw.groupBy(" p.id, p.component_id, p.part_id, p.part_name, d.error_msg ");
        List<ReportPreNestErrResVo> list = lantekPushPackageMapper.preNestException(qw);
        return BaseListResVo.of(list, ReportPreNestErrResVo.class);
    }

    public BasePageResVo<ReportPrePlateResVo> preNestPlate(ReportPrePlateReqVo reqVo) {
        QueryWrapper<LantekNestPlate> qw = Wrappers.query();
        qw.eq("o.mater_code", reqVo.getConstructCode());
        qw.eq("plate.texture", reqVo.getTexture());
        qw.eq("plate.norm", reqVo.getThickness());
        if (StringUtils.hasText(reqVo.getNestId())) {
            qw.like("nest.nest_id", reqVo.getNestId());
        }
        if (StringUtils.hasText(reqVo.getStartTime())) {
            qw.ge("nest.nest_date", reqVo.getStartTime());
        }
        if (StringUtils.hasText(reqVo.getEndTime())) {
            qw.le("nest.nest_date", reqVo.getEndTime());
        }
        Page<ReportPrePlateResVo> pageVo = lantekNestPlateMapper.preNestPlate(reqVo.toPage(), qw);
        if (pageVo.getSize() != 0) {
            for (ReportPrePlateResVo resVo : pageVo.getRecords()) {
                if (resVo.getPlateLength() == null) {
                    resVo.setPlateLength(BigDecimal.valueOf(10000));
                }
                if (resVo.getPlateWidth() == null) {
                    resVo.setPlateWidth(BigDecimal.valueOf(2500));
                }
                resVo.setPlateStandard(resVo.getPlateLength() + "*" + resVo.getPlateWidth());
                resVo.setRate(resVo.getRate().setScale(2, RoundingMode.HALF_UP));
                BigDecimal cutLength = resVo.getCutLength1().add(resVo.getCutLength2());
                resVo.setTotalCutLength(cutLength.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
                resVo.setCutTime(resVo.getCutTime().divide(new BigDecimal(60), 2, RoundingMode.HALF_UP));
            }
        }
        return BasePageResVo.of(pageVo, ReportPrePlateResVo.class);
    }

    public BasePageResVo<ReportPrePlateResVo> preNestPlateNew(ReportPrePlateNewReqVo reqVo) {
        QueryWrapper<LantekNestPlate> qw = Wrappers.query();
        qw.likeRight("plate.nest_id", reqVo.getPreNestCode());
        qw.eq("plate.texture", reqVo.getTexture());
        qw.eq("plate.norm", reqVo.getThickness());
        if (StringUtils.hasText(reqVo.getNestId())) {
            qw.like("nest.nest_id", reqVo.getNestId());
        }
        if (StringUtils.hasText(reqVo.getStartTime())) {
            qw.ge("nest.nest_date", reqVo.getStartTime());
        }
        if (StringUtils.hasText(reqVo.getEndTime())) {
            qw.le("nest.nest_date", reqVo.getEndTime());
        }
        Page<ReportPrePlateResVo> pageVo = lantekNestPlateMapper.preNestPlate(reqVo.toPage(), qw);
        if (pageVo.getSize() != 0) {
            for (ReportPrePlateResVo resVo : pageVo.getRecords()) {
                if (resVo.getPlateLength() == null) {
                    resVo.setPlateLength(BigDecimal.valueOf(10000));
                }
                if (resVo.getPlateWidth() == null) {
                    resVo.setPlateWidth(BigDecimal.valueOf(2500));
                }
                resVo.setPlateStandard(resVo.getPlateLength() + "*" + resVo.getPlateWidth());
                resVo.setRate(resVo.getRate().setScale(2, RoundingMode.HALF_UP));
                BigDecimal cutLength = resVo.getCutLength1().add(resVo.getCutLength2());
                resVo.setTotalCutLength(cutLength.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
                resVo.setCutTime(resVo.getCutTime().divide(new BigDecimal(60), 2, RoundingMode.HALF_UP));
            }
        }
        return BasePageResVo.of(pageVo, ReportPrePlateResVo.class);
    }

    public BaseListResVo<ReportPrePartResVo> preNestPart(ReportPrePartReqVo reqVo) {
        QueryWrapper<LantekNestPart> qw = Wrappers.query();
        qw.eq("part.plate_code", reqVo.getPlateCode());
        qw.eq("nest.nest_id", reqVo.getNestId());
        List<ReportPrePartResVo> list = lantekNestPartMapper.preNestPart(qw);
        return BaseListResVo.of(list, ReportPrePartResVo.class);
    }

    public ReportNestReportPdaResVo nestReportPda(ReportNestReportPdaReqVo reqVo) {

        ReportNestReportPdaResVo nestingReportVo = new ReportNestReportPdaResVo();

        ReportNestReportPdaNestInfoVo nestingInfoVo = new ReportNestReportPdaNestInfoVo();
        ReportNestReportPdaUsedPlatesVo nestingUsedPlatesVo = new ReportNestReportPdaUsedPlatesVo();
        ReportNestReportPdaTextureUsedVo nestingTextureUsedVo = new ReportNestReportPdaTextureUsedVo();
        List<ReportNestReportPdaProductInfosVo> productInfos = new ArrayList<>();
        List<ReportNestReportPdaPartInfosVo> partInfos = new ArrayList<>();

        SinoCamReceiveNestNest nestNest = sinoCamReceiveNestNestMapper.lambdaQuery().eq(SinoCamReceiveNestNest::getNestId, reqVo.getNestId()).one();
        if (nestNest == null) {
            throw SyExceptionUtils.e("未查询到当前套料数据：{}", reqVo.getNestId());
        }
        List<SinoCamReceiveNestPlate> nestPlates = sinoCamReceiveNestPlateMapper.lambdaQuery().eq(SinoCamReceiveNestPlate::getNestId, nestNest.getNestId()).list();
        SinoCamReceiveNestPlate nestPlate = nestPlates.get(0);
        List<SinoCamReceiveNestPart> nestParts = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getNestId, nestNest.getNestId()).list();
        // List<SinoCamReceiveNestPart> plateNestParts = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getNestId, nestNest.getNestId()).eq(SinoCamReceiveNestPart::getPlateCode, nestPlate.getStockListNo()).list();
        List<SinoCamReceiveNestExcess> nestExcesses = sinoCamReceiveNestExcessMapper.lambdaQuery().eq(SinoCamReceiveNestExcess::getNestId, nestNest.getNestId()).list();
        Map<String, SinoCamReceiveNestExcess> nestExcessMap = nestExcesses.stream().collect(Collectors.toMap(SinoCamReceiveNestExcess::getStockListNo, Function.identity()));
        SinoCamReceiveNestExcess excess = nestExcessMap.get(nestPlate.getStockListNo());
        List<SinoCamReceiveNestMove> nestMoves = sinoCamReceiveNestMoveMapper.lambdaQuery().eq(SinoCamReceiveNestMove::getNestId, nestNest.getNestId()).orderByAsc(SinoCamReceiveNestMove::getMoveType).list();

        Plate plate = plateMapper.lambdaQuery().eq(Plate::getMaterCode, nestPlate.getStockListNo()).one();

        // 套料信息
        nestingInfoVo.setNestingNo(nestNest.getNestId());
        nestingInfoVo.setWorkPlaceNo(nestNest.getOptionId());
        nestingInfoVo.setTechnology(nestNest.getOptionId());
        nestingInfoVo.setCreateName(nestNest.getNester());
        nestingInfoVo.setDueDate(nestNest.getNeedDate());
        nestingInfoVo.setNestingSize(nestPlate.getWidth().setScale(0, RoundingMode.HALF_UP) + "*" + nestPlate.getLength().setScale(0, RoundingMode.HALF_UP) + "*" + nestPlate.getNorm());
        nestingInfoVo.setNestingPath(String.format(projectConfig.getUrlPre(), nestingInfoVo.getNestingNo(), nestPlate.getPngUrl()));

        // Used Plates
        BigDecimal nestWeight = plate.getNestWeight();
        BigDecimal nestRate = plate.getNestRate().divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);
        BigDecimal maoWeight = nestWeight.divide(nestRate, 8, RoundingMode.HALF_UP);
        BigDecimal feiWeight = maoWeight.subtract(nestWeight);
        BigDecimal yuWeight = excess != null ? excess.getWeight() : null;
        BigDecimal faWeight = plate.getWeight().subtract(feiWeight);

        nestingUsedPlatesVo.setPlateNo(nestPlate.getStockListNo());
        nestingUsedPlatesVo.setStackingNo(nestPlate.getPositionCode());
        nestingUsedPlatesVo.setBatchNo(nestPlate.getHeatNumber()); // 炉批号
        nestingUsedPlatesVo.setTexture(nestPlate.getTexture());
        nestingUsedPlatesVo.setTotalCount(1);
        nestingUsedPlatesVo.setReportedWeight(faWeight.setScale(2, RoundingMode.HALF_UP));
        nestingUsedPlatesVo.setUsedWeight(maoWeight.setScale(2, RoundingMode.HALF_UP));
        nestingUsedPlatesVo.setPlateSize(nestPlate.getWidth().setScale(0, RoundingMode.HALF_UP) + "*" + nestPlate.getLength().setScale(0, RoundingMode.HALF_UP) + "*" + nestPlate.getNorm());
        nestingUsedPlatesVo.setUsedArea(nestPlate.getNestArea());
        nestingUsedPlatesVo.setUsedRate(nestNest.getRate().setScale(2, RoundingMode.HALF_UP));

        // 材料使用
        Integer orderId = nestParts.get(0).getOrderId();
        Order order = orderMapper.lambdaQuery().eq(Order::getId, orderId).one();
        nestingTextureUsedVo.setOrderNo(order.getOrderCode());
        nestingTextureUsedVo.setReportWeight(plate.getWeight().setScale(2, RoundingMode.HALF_UP));
        nestingTextureUsedVo.setNetWeight(nestWeight.setScale(2, RoundingMode.HALF_UP));
        nestingTextureUsedVo.setGrossWeight(maoWeight.setScale(2, RoundingMode.HALF_UP));
        nestingTextureUsedVo.setReturnWeight(yuWeight);
        nestingTextureUsedVo.setAbandonWeight1(feiWeight.setScale(2, RoundingMode.HALF_UP));
        nestingTextureUsedVo.setAbandonWeight2(null);
        nestingTextureUsedVo.setUsedRate(nestNest.getRate().setScale(2, RoundingMode.HALF_UP));

        ReportNestReportPdaProductInfosVo infoVoTotal = new ReportNestReportPdaProductInfosVo();
        infoVoTotal.setCuttingType("total");
        infoVoTotal.setLength(new BigDecimal(0));
        infoVoTotal.setSpeed(null);
        infoVoTotal.setCuttingTime("0");
        int cuttingTimeInt = 0;
        infoVoTotal.setHoleCount(0);
        infoVoTotal.setHolePerTime("0");
        infoVoTotal.setHoleTime("0");
        int holeTimeInt = 0;
        infoVoTotal.setTotalTime("0");
        int totalTimeInt = 0;
        // 加工次数
        for (SinoCamReceiveNestMove nestMove : nestMoves) {
            ReportNestReportPdaProductInfosVo vo = new ReportNestReportPdaProductInfosVo();
            vo.setCuttingType(nestMove.getMoveType().toString());
            vo.setLength(nestMove.getCutLength().setScale(2, RoundingMode.HALF_UP));
            vo.setSpeed(nestMove.getCutRate().setScale(2, RoundingMode.HALF_UP));
            vo.setCuttingTime(SecondTimeChangeUtils.change(nestMove.getMoveTime()));
            vo.setHoleCount(nestMove.getHoleCount());
            vo.setHolePerTime(SecondTimeChangeUtils.change(nestMove.getHoleTime()));
            vo.setHoleTime(SecondTimeChangeUtils.change(nestMove.getTotalHoleTime()));
            int totalTime = nestMove.getMoveTime() + nestMove.getTotalHoleTime();
            vo.setTotalTime(SecondTimeChangeUtils.change(totalTime));
            productInfos.add(vo);
            infoVoTotal.setLength(nestMove.getCutLength().add(infoVoTotal.getLength()).setScale(2, RoundingMode.HALF_UP));
            cuttingTimeInt = nestMove.getMoveTime() + cuttingTimeInt;
            infoVoTotal.setCuttingTime(SecondTimeChangeUtils.change(cuttingTimeInt));
            infoVoTotal.setHoleCount(nestMove.getHoleCount());
            holeTimeInt = nestMove.getTotalHoleTime() + holeTimeInt;
            infoVoTotal.setHoleTime(SecondTimeChangeUtils.change(holeTimeInt));
            if (nestMove.getMoveType() == 1) {
                totalTimeInt = nestMove.getTotalCutTime() + totalTimeInt;
                infoVoTotal.setTotalTime(SecondTimeChangeUtils.change(totalTimeInt));
            }
        }
        productInfos.add(infoVoTotal);

        List<Order> orderList = orderMapper.lambdaQuery().list();
        Map<Integer, Order> orderMap = orderList.stream().collect(Collectors.toMap(Order::getId, Function.identity()));
        // 零件清单
        List<OrderBom> orderBomList = orderBomMapper.lambdaQuery()
//                .eq(OrderBom::getOrderId, split[0])
                .ne(OrderBom::getWorkChain, "WL")
                .isNotNull(OrderBom::getTexture).list();
        Map<String, OrderBom> orderBomMap = orderBomList.stream().collect(Collectors.toMap(OrderBom::getPlmId, Function.identity(), (a, b) -> b));
        for (SinoCamReceiveNestPart nestPart : nestParts) {
            Integer partOrderId = nestPart.getOrderId();
            Order orderPart = orderMap.get(partOrderId);
            OrderBom orderBom = orderBomMap.get(nestPart.getPartId());
            String workChain = orderBom.getWorkChain();
            String[] chainSplits = workChain.split("-");
            String station = getStation(chainSplits, orderBom.getPid());
            ReportNestReportPdaPartInfosVo vo = new ReportNestReportPdaPartInfosVo();
            vo.setOrderNo(orderPart.getOrderCode());
            vo.setSize("δ" + nestPart.getThickness().setScale(0, RoundingMode.HALF_UP) + "*" + nestPart.getWidth().setScale(0, RoundingMode.HALF_UP) + "*" + nestPart.getLength().setScale(0, RoundingMode.HALF_UP));
            vo.setDueDate(nestNest.getNeedDate());
            vo.setOrderCount(nestPart.getQuantity().toString());
            vo.setPlmId(nestPart.getPartId());
            vo.setNestingCount(nestPart.getQuantity());
            vo.setPartName(nestPart.getPartName());
            vo.setPerWeight(nestPart.getNetWeight().setScale(2, RoundingMode.HALF_UP));
            vo.setNextStation(station);
            vo.setTotalWeight(nestPart.getNetWeight().multiply(new BigDecimal(nestPart.getQuantity())).setScale(2, RoundingMode.HALF_UP));
            vo.setPartPath(String.format(projectConfig.getUrlPre(), vo.getPlmId(), nestPart.getPartMapUrl()));
            partInfos.add(vo);
        }


//        nestingInfoVo.setNestingPath(nestingInfoVo.getNestingPath().replace(ltkPngUrl, "/images/"));
//        for (ReportNestReportPdaPartInfosVo partInfo : partInfos) {
//            partInfo.setPartPath(partInfo.getPartPath().replace(ltkPngUrl, "/images/"));
//        }

        nestingReportVo.setNestInfo(nestingInfoVo);
        nestingReportVo.setUsedPlates(nestingUsedPlatesVo);
        nestingReportVo.setTextureUsed(nestingTextureUsedVo);
        nestingReportVo.setProductInfos(productInfos);
        nestingReportVo.setPartInfos(partInfos);
        return nestingReportVo;
    }

    public String getStation(String[] chainSplits, Integer pid) {
        List<String> chainList = Arrays.asList(chainSplits);
        int index = chainList.indexOf("FJ");
        if (index >= 0 && index < chainList.size() - 1) {
            return chainList.get(index + 1);
        } else {
            OrderBom orderBom = orderBomMapper.selectById(pid);
            String workChain = orderBom.getWorkChain();
            String[] split = workChain.split("-");
            if ("PP".equals(split[0]) || "PZ".equals(split[0])) {
                return "KJ";
            }
            return split[0];
        }
    }

    public ReportNestPlateNeedVo nestPlateNeed(ReportNestPlateNeedReqVo reqVo) {
        List<DictData> dictData = dictDataMapper.plateTextureReplace();
        Map<String, String> map = dictData.stream().collect(Collectors.toMap(DictData::getDictLabel, DictData::getDictValue));

        ReportNestPlateNeedVo resVo = new ReportNestPlateNeedVo();

        QueryWrapper<OrderBom> qw = Wrappers.query();
        if (StringUtils.hasText(reqVo.getConstructCode())) {
            qw.like("o.construct_no", reqVo.getConstructCode());
        }
        if (StringUtils.hasText(reqVo.getMaterCode())) {
            qw.like("o.mater_code", reqVo.getMaterCode());
        }
        if (StringUtils.hasText(reqVo.getMaterName())) {
            qw.like("o.mater_name", reqVo.getMaterName());
        }
        if (StringUtils.hasText(reqVo.getTexture())) {
            qw.like("ob.texture", reqVo.getTexture());
        }
        if (reqVo.getThickness() != null) {
            qw.eq("ob.mater_high", reqVo.getThickness());
        }
        if (reqVo.getStartTime() != null) {
            qw.ge("startTime", reqVo.getStartTime().plusDays(7) + " 00:00:00");
        }
        if (reqVo.getEndTime() != null) {
            qw.le("startTime", reqVo.getEndTime().plusDays(7) + " 23:59:59");
        }
        qw.eq("ob.mater_type", "Platepart");
        qw.ne("o.order_type", 2);
        qw.ne("o.order_status", 10);
        if (reqVo.getHistoryFlag() == null || reqVo.getHistoryFlag() != 1) {
//            qw.le("o.order_status", 7); // 数据形成闭环，订单完成后数据清除出查询列表
            qw.and(wp->wp.le("o.order_status", 8)
                    .or()
                    .eq("o.order_status", 9).le("o.actual_end_date_time", LocalDate.now().plusMonths(1)));
        } else {
            qw.eq("o.order_status", 9);
            qw.lt("o.actual_end_date_time", LocalDate.now().plusMonths(1));
        }
        qw.groupBy(" o.construct_no, o.mater_code, o.mater_name, o.order_qty, ob.texture, ob.mater_high ");
        Page<ReportNestPlateNeedResVo> pageVo = orderBomMapper.nestPlateNeed(reqVo.toPage(), qw);

        if (CollUtil.isEmpty(pageVo.getRecords())) {
            resVo.setTotal(0);
            resVo.setData(new ArrayList<>());
            return resVo;
        }

        List<ReportNestPlateNeedResVo> reportNestPlateNeedResVos = TextureReplaceUtils.needReplace(pageVo.getRecords(), map);
        pageVo.setRecords(reportNestPlateNeedResVos);

        PlatePreNormVo stockReqVo = new PlatePreNormVo();
        List<String> textureList = pageVo.getRecords().stream().map(ReportNestPlateNeedResVo::getTexture).collect(Collectors.toList());
        List<BigDecimal> thicknessList = pageVo.getRecords().stream().map(ReportNestPlateNeedResVo::getThickness).collect(Collectors.toList());
        stockReqVo.setTexture(textureList);
        stockReqVo.setThickness(thicknessList);
        PlatePreStockVo stockResVo = apsWmsApiClient.preNestPlateStock(stockReqVo);
        List<PlatePreNestStockVo> platePreNestStockVos = TextureReplaceUtils.plateReplace(stockResVo.getPlateInfo(), map);
        stockResVo.setPlateInfo(platePreNestStockVos);
        Map<String, PlatePreNestStockVo> stockVoMap = stockResVo.getPlateInfo().stream().collect(Collectors.toMap(PlatePreNestStockVo::getStandard, Function.identity()));

        if (pageVo.getSize() != 0) {
            for (ReportNestPlateNeedResVo vo : pageVo.getRecords()) {
                if (vo.getStandardPlateLength() == null) {
                    vo.setStandardPlateLength(BigDecimal.valueOf(10000));
                }
                if (vo.getStandardPlateWidth() == null) {
                    vo.setStandardPlateWidth(BigDecimal.valueOf(2500));
                }
                if (vo.getPlateRate() == null) {
                    vo.setPlateRate(85);
                }
                PlatePreNestStockVo stockVo = stockVoMap.get(vo.getTexture() + "δ" + vo.getThickness());
                vo.setStandardPlate(vo.getStandardPlateLength() + "*" + vo.getStandardPlateWidth());
                if (stockVo == null) {
                    stockVo = new PlatePreNestStockVo();
                    stockVo.setAmount(0);
                    stockVo.setWeight(BigDecimal.ZERO);
                }
                vo.setRealPlateAmount(stockVo.getAmount());
                vo.setRealPlateWeight(stockVo.getWeight().divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
                if (vo.getPartWeight().compareTo(BigDecimal.ZERO) == 0) {
                    List<String> list = orderBomMapper.findNullWeight(vo.getConstructCode());
                    vo.setInfoMsg("质量为空的零件PLMID：" + list.toString());
                    vo.setPlanPlateWeight(BigDecimal.valueOf(0));
                    vo.setBuyPlateWeight(BigDecimal.valueOf(0));
                    vo.setPlanAmount(0);
                    vo.setBuyPlateAmount(0);
                    vo.setPartWeight(BigDecimal.ZERO);
                    continue;
                }
                BigDecimal planPlateWeight = vo.getPartWeight().divide(new BigDecimal(1000), 5, RoundingMode.HALF_UP);
                BigDecimal plateRate = BigDecimal.valueOf(vo.getPlateRate()).divide(new BigDecimal(100), 5, RoundingMode.HALF_UP);
                vo.setPlanPlateWeight(planPlateWeight.divide(plateRate, 2, RoundingMode.HALF_UP));
                vo.setBuyPlateWeight(vo.getRealPlateWeight().subtract(vo.getPlanPlateWeight()));
                BigDecimal plateT = vo.getStandardPlateLength().divide(BigDecimal.valueOf(1000), 5, RoundingMode.HALF_UP)
                        .multiply(vo.getStandardPlateWidth().divide(BigDecimal.valueOf(1000), 5, RoundingMode.HALF_UP))
                        .multiply(vo.getThickness().divide(BigDecimal.valueOf(1000), 5, RoundingMode.HALF_UP));
                BigDecimal am = vo.getPlanPlateWeight().divide(BigDecimal.valueOf(7.85), 5, RoundingMode.HALF_UP).divide(plateT, 5, RoundingMode.HALF_UP);
                vo.setPlanAmount(am.setScale(0, RoundingMode.UP).intValue());
                vo.setBuyPlateAmount(vo.getRealPlateAmount() - vo.getPlanAmount());
                if (vo.getDeliveryTime() == null) {
                    vo.setInfoMsg("未进行排产。");
                }
                vo.setPartWeight(vo.getPartWeight().setScale(2, RoundingMode.HALF_UP));
                vo.setDeliveryTime(vo.getDeliveryTime().minusDays(7));
            }

            Integer totalPlanPlateAmount = pageVo.getRecords().stream().map(ReportNestPlateNeedResVo::getPlanAmount).reduce(0, Integer::sum);
            resVo.setTotalPlanPlateAmount(totalPlanPlateAmount);
            resVo.setTotalRealPlateAmount(stockResVo.getPlateCount());
            resVo.setTotalBuyPlateAmount(resVo.getTotalRealPlateAmount() - resVo.getTotalPlanPlateAmount());
            BigDecimal totalPlanPlateWeight = pageVo.getRecords().stream().map(ReportNestPlateNeedResVo::getPlanPlateWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
            resVo.setTotalPlanPlateWeight(totalPlanPlateWeight);
            resVo.setTotalRealPlateWeight(stockResVo.getPlateWeight().divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
            resVo.setTotalBuyPlateWeight(resVo.getTotalRealPlateWeight().subtract(resVo.getTotalPlanPlateWeight()));
            BigDecimal totalPartWeight = pageVo.getRecords().stream().map(ReportNestPlateNeedResVo::getPartWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
            resVo.setTotalPartWeight(totalPartWeight.setScale(2, RoundingMode.HALF_UP));
            resVo.setTotal(pageVo.getTotal());
            resVo.setData(pageVo.getRecords());

        }
        return resVo;
    }

    public ReportNestPlateSumVo nestPlateSum(ReportNestPlateSumReqVo reqVo) {
        List<DictData> dictData = dictDataMapper.plateTextureReplace();
        Map<String, String> map = dictData.stream().collect(Collectors.toMap(DictData::getDictLabel, DictData::getDictValue));

        ReportNestPlateSumVo resVo = new ReportNestPlateSumVo();

        if (!StringUtils.hasText(reqVo.getConstructCode())) {
            return new ReportNestPlateSumVo();
        }

        QueryWrapper<OrderBom> qw = Wrappers.query();
        qw.eq("o.construct_no", reqVo.getConstructCode());
        if (StringUtils.hasText(reqVo.getTexture())) {
            qw.like("ob.texture", reqVo.getTexture());
        }
        if (reqVo.getThickness() != null) {
            qw.eq("ob.mater_high", reqVo.getThickness());
        }
        qw.eq("ob.mater_type", "Platepart");
        qw.groupBy(" o.construct_no, ob.texture, ob.mater_high ");
        qw.orderByAsc(" ob.texture, ob.mater_high ");
        List<ReportNestPlateSumResVo> listVoOld = orderBomMapper.nestPlateSum(qw);

        if (CollUtil.isEmpty(listVoOld)) {
            resVo.setInfoList(new ArrayList<>());
            return resVo;
        }

        List<ReportNestPlateSumResVo> listVo = TextureReplaceUtils.sumReplace(listVoOld, map);

        PlatePreNormVo stockReqVo = new PlatePreNormVo();
        List<String> textureList = listVo.stream().map(ReportNestPlateSumResVo::getTexture).collect(Collectors.toList());
        List<BigDecimal> thicknessList = listVo.stream().map(ReportNestPlateSumResVo::getThickness).collect(Collectors.toList());
        stockReqVo.setTexture(textureList);
        stockReqVo.setThickness(thicknessList);
        PlatePreStockVo stockResVo = apsWmsApiClient.preNestPlateStock(stockReqVo);
        Map<String, PlatePreNestStockVo> stockVoMap = stockResVo.getPlateInfo().stream().collect(Collectors.toMap(PlatePreNestStockVo::getStandard, Function.identity()));

        if (CollUtil.isNotEmpty(listVo)) {
            for (ReportNestPlateSumResVo vo : listVo) {
                if (vo.getStandardPlateLength() == null) {
                    vo.setStandardPlateLength(BigDecimal.valueOf(10000));
                }
                if (vo.getStandardPlateWidth() == null) {
                    vo.setStandardPlateWidth(BigDecimal.valueOf(2500));
                }
                if (vo.getPlateRate() == null) {
                    vo.setPlateRate(85);
                }
                PlatePreNestStockVo stockVo = stockVoMap.get(vo.getTexture() + "δ" + vo.getThickness());
                vo.setStandardPlate(vo.getStandardPlateLength() + "*" + vo.getStandardPlateWidth());
                if (stockVo == null) {
                    stockVo = new PlatePreNestStockVo();
                    stockVo.setAmount(0);
                    stockVo.setWeight(BigDecimal.ZERO);
                }
                vo.setRealPlateAmount(stockVo.getAmount());
                vo.setRealPlateWeight(stockVo.getWeight().divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
                if (vo.getPartWeight().compareTo(BigDecimal.ZERO) == 0) {
                    List<String> list = orderBomMapper.findNullWeight(vo.getConstructCode());
                    vo.setInfoMsg("质量为空的零件PLMID：" + list.toString());
                    vo.setPlanPlateWeight(BigDecimal.valueOf(0));
                    vo.setBuyPlateWeight(BigDecimal.valueOf(0));
                    vo.setPlanAmount(0);
                    vo.setBuyPlateAmount(0);
                    vo.setPartWeight(BigDecimal.ZERO);
                    continue;
                }
                BigDecimal planPlateWeight = vo.getPartWeight().divide(new BigDecimal(1000), 5, RoundingMode.HALF_UP);
                BigDecimal plateRate = BigDecimal.valueOf(vo.getPlateRate()).divide(new BigDecimal(100), 5, RoundingMode.HALF_UP);
                vo.setPlanPlateWeight(planPlateWeight.divide(plateRate, 2, RoundingMode.HALF_UP));
                vo.setBuyPlateWeight(vo.getRealPlateWeight().subtract(vo.getPlanPlateWeight()));
                BigDecimal plateT = vo.getStandardPlateLength().divide(BigDecimal.valueOf(1000), 5, RoundingMode.HALF_UP)
                        .multiply(vo.getStandardPlateWidth().divide(BigDecimal.valueOf(1000), 5, RoundingMode.HALF_UP))
                        .multiply(vo.getThickness().divide(BigDecimal.valueOf(1000), 5, RoundingMode.HALF_UP));
                BigDecimal am = vo.getPlanPlateWeight().divide(BigDecimal.valueOf(7.85), 5, RoundingMode.HALF_UP).divide(plateT, 5, RoundingMode.HALF_UP);
                vo.setPlanAmount(am.setScale(0, RoundingMode.UP).intValue());
                vo.setBuyPlateAmount(vo.getRealPlateAmount() - vo.getPlanAmount());
                vo.setPartWeight(vo.getPartWeight().setScale(2, RoundingMode.HALF_UP));
            }

            Integer totalPlanPlateAmount = listVo.stream().map(ReportNestPlateSumResVo::getPlanAmount).reduce(0, Integer::sum);
            resVo.setTotalPlanPlateAmount(totalPlanPlateAmount);
            resVo.setTotalRealPlateAmount(stockResVo.getPlateCount());
            resVo.setTotalBuyPlateAmount(resVo.getTotalRealPlateAmount() - resVo.getTotalPlanPlateAmount());
            BigDecimal totalPlanPlateWeight = listVo.stream().map(ReportNestPlateSumResVo::getPlanPlateWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
            resVo.setTotalPlanPlateWeight(totalPlanPlateWeight);
            resVo.setTotalRealPlateWeight(stockResVo.getPlateWeight().divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
            resVo.setTotalBuyPlateWeight(resVo.getTotalRealPlateWeight().subtract(resVo.getTotalPlanPlateWeight()));
            BigDecimal totalPartWeight = listVo.stream().map(ReportNestPlateSumResVo::getPartWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
            resVo.setTotalPartWeight(totalPartWeight.setScale(2, RoundingMode.HALF_UP));
            resVo.setInfoList(listVo);
        }

        return resVo;
    }

    public BasePageResVo<ReportNestPartInfoResVo> nestPartInfo(ReportNestPartInfoReqVo reqVo) {
        List<DictData> dictData = dictDataMapper.plateTextureReplace();
        Map<String, String> map = dictData.stream().collect(Collectors.toMap(DictData::getDictValue, DictData::getDictLabel));
        List<String> texture = new ArrayList<>();
        texture.add(reqVo.getTexture());
        if (StringUtils.hasText(reqVo.getTexture())) {
            texture.add(map.get(reqVo.getTexture()));
        }

        QueryWrapper<OrderBom> qw = Wrappers.query();
        qw.eq("o.mater_code", reqVo.getMaterCode());
        qw.in("ob.texture", texture);
        qw.eq("ob.mater_high", reqVo.getThickness());
        if (StringUtils.hasText(reqVo.getPlmId())) {
            qw.like("ob.plm_id", reqVo.getPlmId());
        }
        if (StringUtils.hasText(reqVo.getPartName())) {
            qw.like("ob.mater_name", reqVo.getPartName());
        }
        qw.eq("ob.mater_type", "Platepart");
        qw.ne("o.order_type", 2);
        Page<ReportNestPartInfoResVo> pageVo = orderBomMapper.nestPartInfo(reqVo.toPage(), qw);
        return BasePageResVo.of(pageVo, ReportNestPartInfoResVo.class);
    }

    public BasePageResVo<ReportWireNeedResVo> nestWireNeed(ReportWireNeedReqVo reqVo) {
        // 修改需要查询的表：tb_order_accessories，目前表中数据全为MBD来源，待验证
//        QueryWrapper<OrderBom> qw = Wrappers.query();
//        qw.likeRight("ob.plm_id", "020");
//        qw.ge("o.order_status", 5);
////        qw.ne("o.order_type", 2); // 限制数据来源，MBD为预套料数据，ERP为正式套料数据
//        if (reqVo.getHistoryFlag() == null || reqVo.getHistoryFlag() != 1) {
//            qw.le("o.order_status", 7); // 数据形成闭环，订单完成后数据清除出查询列表
//        } else {
//            qw.gt("o.order_status", 7);
//        }
//        if (StringUtils.hasText(reqVo.getConstructCode())) {
//            qw.like("o.mater_code", reqVo.getConstructCode());
//        }
//        if (StringUtils.hasText(reqVo.getTexture())) {
//            qw.like("ob.standards", reqVo.getTexture());
//        }
//        if (reqVo.getStartTime() != null) {
//            qw.ge("startTime", reqVo.getStartTime().plusDays(2) + " 00:00:00");
//        }
//        if (reqVo.getEndTime() != null) {
//            qw.le("startTime", reqVo.getEndTime().plusDays(2) + " 23:59:59");
//        }
//        Page<ReportWireNeedResVo> pageVo = orderBomMapper.nestWireNeed(reqVo.toPage(), qw);
        QueryWrapper<OrderAccessories> qw = Wrappers.query();
        qw.in("o.order_type", 1,3,4);
        qw.likeRight("a.mater_code", "0201");
        if (StringUtils.hasText(reqVo.getConstructCode())) {
            qw.like("o.construct_no", reqVo.getConstructCode());
        }
        if (StringUtils.hasText(reqVo.getMaterCode())) {
            qw.like("o.mater_code", reqVo.getMaterCode());
        }
        if (StringUtils.hasText(reqVo.getMaterName())) {
            qw.like("o.mater_name", reqVo.getMaterName());
        }
        if  (StringUtils.hasText(reqVo.getTexture())) {
            qw.like("a.model", reqVo.getTexture());
        }
        if (reqVo.getStartTime() != null) {
            qw.ge("startTime", reqVo.getStartTime().plusDays(2) + " 00:00:00");
        }
        if (reqVo.getEndTime() != null) {
            qw.le("startTime", reqVo.getEndTime().plusDays(2) + " 23:59:59");
        }
        Page<ReportWireNeedResVo> pageVo = orderAccessoriesMapper.nestWireNeed(reqVo.toPage(), qw);

        try  {
            Map<String, ReportWireStockResVo> info = ltkInfo();
            for (ReportWireNeedResVo vo : pageVo.getRecords()) {
                String texture = vo.getTexture();
                String[] split = texture.split(",");
                ReportWireStockResVo stockVo = info.get(split[0]);
                if (stockVo != null) {
                    vo.setStockWeight(stockVo.getMaterialWeight());
                } else {
                    vo.setStockWeight(BigDecimal.ZERO);
                }
                if (vo.getPlanNeedTime() != null) {
                    vo.setPlanNeedTime(vo.getPlanNeedTime().minusDays(2));
                }
                vo.setBuyWeight(vo.getStockWeight().subtract(vo.getNeedWeight()));
            }
        } catch (Exception e) {
            e.printStackTrace();

            for (ReportWireNeedResVo vo : pageVo.getRecords()) {
                vo.setStockWeight(BigDecimal.ZERO);
                if (vo.getPlanNeedTime() != null) {
                    vo.setPlanNeedTime(vo.getPlanNeedTime().minusDays(2));
                }
                vo.setBuyWeight(vo.getStockWeight().subtract(vo.getNeedWeight()));
            }
        }

        return BasePageResVo.of(pageVo, ReportWireNeedResVo.class);
    }

    public BasePageResVo<ReportSprayNeedResVo> nestSprayNeed(ReportSprayNeedReqVo reqVo) {
        // 修改需要查询的表：tb_order_accessories，目前表中数据全为MBD来源，待验证
//        QueryWrapper<OrderBom> qw = Wrappers.query();
//        qw.likeRight("ob.plm_id", "050");
//        qw.ge("o.order_status", 5);
////        qw.ne("o.order_type", 2); // 限制数据来源，MBD为预套料数据，ERP为正式套料数据
//        if (reqVo.getHistoryFlag() == null || reqVo.getHistoryFlag() != 1) {
//            qw.le("o.order_status", 7); // 数据形成闭环，订单完成后数据清除出查询列表
//        } else {
//            qw.gt("o.order_status", 7);
//        }
//        if (StringUtils.hasText(reqVo.getTexture())) {
//            qw.like("ob.mater_name", reqVo.getTexture());
//        }
//        if (StringUtils.hasText(reqVo.getConstructCode())) {
//            qw.like("o.mater_code", reqVo.getConstructCode());
//        }
//        if (reqVo.getStartTime() != null) {
//            qw.ge("startTime", reqVo.getStartTime().plusDays(2) + " 00:00:00");
//        }
//        if (reqVo.getEndTime() != null) {
//            qw.le("startTime", reqVo.getEndTime().plusDays(2) + " 23:59:59");
//        }
//        Page<ReportSprayNeedResVo> pageVo = orderBomMapper.nestSprayNeed(reqVo.toPage(), qw);
        QueryWrapper<OrderAccessories> qw = Wrappers.query();
        qw.in("o.order_type", 1,3,4);
        qw.and(wq->wq.likeRight("a.mater_code", "0503")
                .or()
                .likeRight("a.mater_code", "0504"));
        if (StringUtils.hasText(reqVo.getConstructCode())) {
            qw.like("o.construct_no", reqVo.getConstructCode());
        }
        if (StringUtils.hasText(reqVo.getMaterCode())) {
            qw.like("o.mater_code", reqVo.getMaterCode());
        }
        if (StringUtils.hasText(reqVo.getMaterName())) {
            qw.like("o.mater_name", reqVo.getMaterName());
        }
        if  (StringUtils.hasText(reqVo.getTexture())) {
            qw.like("a.mater_name", reqVo.getTexture());
        }
        if (reqVo.getStartTime() != null) {
            qw.ge("startTime", reqVo.getStartTime().plusDays(2) + " 00:00:00");
        }
        if (reqVo.getEndTime() != null) {
            qw.le("startTime", reqVo.getEndTime().plusDays(2) + " 23:59:59");
        }
        Page<ReportSprayNeedResVo> pageVo = orderAccessoriesMapper.nestSprayNeed(reqVo.toPage(), qw);

        for (ReportSprayNeedResVo vo : pageVo.getRecords()) {
            if (vo.getPlanNeedTime() != null) {
                vo.setPlanNeedTime(vo.getPlanNeedTime().minusDays(2));
            }
            vo.setStockWeight(BigDecimal.ZERO);
            vo.setBuyWeight(vo.getStockWeight().subtract(vo.getNeedWeight()));
        }

        return BasePageResVo.of(pageVo, ReportSprayNeedResVo.class);
    }

    public void unlockStock(ReportUnlockStockReqVo reqVo) {
        Result result = apsWmsApiClient.unlockStock(reqVo);
        String userCode = SySecurityUtils.getUserCode();
        String reqContent = "stock_id：" + reqVo.getStockId() + "___" + "user_code：" + userCode;
        if (result.getCode() == 0) {
            LogContent log = new LogContent();
            log.setLogType(2);
            log.setReqContent(reqContent);
            log.setResContent(result.getMessage());
            logContentMapper.insert(log);
        } else {
            LogContent log = new LogContent();
            log.setLogType(2);
            log.setReqContent(reqContent);
            log.setResContent(result.getMessage());
            logContentMapper.insert(log);
            throw SyExceptionUtils.e("解锁失败：{}", result.getMessage());
        }
    }

    public BaseListResVo<ReportProAbilityResVo> proAbility(ReportProAbilityReqVo reqVo) {

        String[] split = reqVo.getId().split("\\$");
        if (!split[0].equals("4") && !split[0].equals("3")) {
            throw SyExceptionUtils.e("不支持的查询类型");
        }

        Integer id = Integer.parseInt(split[1]);

        LambdaQueryChainWrapper<ApsWorkDetail> wrapper = apsWorkDetailMapper.lambdaQuery();
        if (split[0].equals("3")) {
            wrapper.eq(ApsWorkDetail::getApsOrderId, id);
        } else {
            ApsWorkOrder apsWorkOrder = apsWorkOrderMapper.selectById(id);

            List<ApsWorkOrder> apsWorkOrderList = apsWorkOrderMapper.lambdaQuery()
//                    .likeRight(ApsWorkOrder::getAssemblyPath, apsWorkOrder.getAssemblyPath())
                    .and(w -> w.likeRight(ApsWorkOrder::getAssemblyPath, apsWorkOrder.getAssemblyPath() + "/").or().eq(ApsWorkOrder::getAssemblyPath, apsWorkOrder.getAssemblyPath()))
                    .eq(ApsWorkOrder::getApsOrderId, apsWorkOrder.getApsOrderId())
                    .in(!reqVo.isChildren(), ApsWorkOrder::getLevel, apsWorkOrder.getLevel(), apsWorkOrder.getLevel() + 1)
                    .list();

            List<Integer> idList = apsWorkOrderList.stream().map(BaseEntity::getId).distinct().collect(Collectors.toList());

            wrapper.in(ApsWorkDetail::getApsWorkOrderId, idList);
        }
        List<ApsWorkDetail> apsWorkDetailList = wrapper.list();
        Map<String, List<ApsWorkDetail>> collect = apsWorkDetailList.stream().collect(Collectors.groupingBy(ApsWorkDetail::getPhaseCode));
        List<ReportProAbilityResVo> collect1 = collect.keySet()
                .stream()
                .map(e -> {
                    ReportProAbilityResVo resVo = new ReportProAbilityResVo();
                    resVo.setPhaseCode(e);

                    List<ApsWorkDetail> apsWorkDetails = collect.get(e);

                    Integer workTimeTotal = apsWorkDetails.stream().map(ApsWorkDetail::getTotalWorkTime).reduce(0, Integer::sum);
                    resVo.setWorkTimeTotal(new BigDecimal(workTimeTotal).divide(new BigDecimal(60), 2, RoundingMode.HALF_UP));

                    BigDecimal phaseTotalCount = apsWorkDetails.stream().map(ApsWorkDetail::getTotalCount).reduce(BigDecimal.ZERO, BigDecimal::add);
                    resVo.setPhaseTotalCount(phaseTotalCount);

                    BigDecimal phaseFinishCount = apsWorkDetails.stream().map(ApsWorkDetail::getFinishCount).reduce(BigDecimal.ZERO, BigDecimal::add);
                    resVo.setPhaseFinishCount(phaseFinishCount);

                    resVo.setPhaseFinishRate(resVo.getPhaseFinishCount().multiply(new BigDecimal(100)).divide(resVo.getPhaseTotalCount(), 2, RoundingMode.HALF_UP));

                    resVo.setActualWorkTime(resVo.getPhaseFinishCount().multiply(resVo.getWorkTimeTotal()));

                    ApsWorkDetail minPlanStartDateTime = apsWorkDetails.stream().min(Comparator.comparing(ApsWorkDetail::getPlanStartDateTime)).orElseGet(ApsWorkDetail::new);
                    resVo.setPlanStartDateTime(minPlanStartDateTime.getPlanStartDateTime());

                    ApsWorkDetail maxPlanStartDateTime = apsWorkDetails.stream().max(Comparator.comparing(ApsWorkDetail::getPlanEndDateTime)).orElseGet(ApsWorkDetail::new);
                    resVo.setPlanEndDateTime(maxPlanStartDateTime.getPlanEndDateTime());


                    ApsWorkDetail minActualStartDateTime = apsWorkDetails.stream().filter(e1 -> e1.getActualStartDateTime() != null).min(Comparator.comparing(ApsWorkDetail::getActualStartDateTime)).orElseGet(ApsWorkDetail::new);

                    resVo.setActualStartDateTime(minActualStartDateTime.getActualStartDateTime());

                    return resVo;
                })
                .collect(Collectors.toList());


        return new BaseListResVo<>(collect1);
    }


    public Map<String, ReportWireStockResVo> ltkInfo() {
        // 设置超时时长，连接超时和读取超时
        Request.Options options = new Request.Options(5L, TimeUnit.SECONDS, 5L, TimeUnit.SECONDS, true);
        Result<List<ReportWireStockResVo>> result = wmsLtkApiClient.ltkInfo(options);
        if (result.getCode() == 0) {
            List<ReportWireStockResVo> data = result.getData();
            return data.stream().collect(Collectors.toMap(ReportWireStockResVo::getMaterialGraphNo, Function.identity(), (a, b) -> b));
        } else {
            return Collections.emptyMap();
        }
    }

    public String receiveNestInfo(String url, String type) throws IOException {

        String path = FileStorageUtils.getFilePath(type);

        try {
            byte[] bytes = HttpUtil.downloadBytes(url);
            FileUtils.writeByteArrayToFile(new File(path), bytes);
        } catch (Exception e) {
            path = url;
        }
        return path;

    }

    public BasePageResVo<ReportWorkOrderPublishResVo> getWorkOrderPublish(ReportWorkOrderPublishReqVo reqVo) {
        QueryWrapper<OrderBom> qw = Wrappers.query();
        qw.like(StringUtils.hasText(reqVo.getWorkChain()), "ob.work_chain", reqVo.getWorkChain());
        qw.like(StringUtils.hasText(reqVo.getProductCode()), "o.mater_code", reqVo.getProductCode());
        qw.like(StringUtils.hasText(reqVo.getMaterCode()), "ob.mater_code", reqVo.getMaterCode());
        qw.like(StringUtils.hasText(reqVo.getMaterName()), "ob.mater_name", reqVo.getMaterName());
        qw.like(StringUtils.hasText(reqVo.getPlmId()), "ob.plm_id", reqVo.getPlmId());
        qw.like(StringUtils.hasText(reqVo.getFaPlmId()), "obp.plm_id", reqVo.getFaPlmId());
        qw.like(StringUtils.hasText(reqVo.getMaterType()), "ob.mater_type", reqVo.getMaterType());
        qw.eq(reqVo.getThickness() != null, "op.thickness", reqVo.getThickness());
        qw.like(StringUtils.hasText(reqVo.getTexture()), "op.texture", reqVo.getTexture());
        qw.like(StringUtils.hasText(reqVo.getErpId()), "ob.erp_code", reqVo.getErpId());
        qw.like(StringUtils.hasText(reqVo.getErpWorkOrderCode()), "ob.work_order_code", reqVo.getErpWorkOrderCode());
        if (reqVo.getStartDate() != null) {
            qw.ge("ob.due_date", reqVo.getStartDate());
        }
        if (reqVo.getEndDate() != null) {
            qw.le("ob.due_date", reqVo.getEndDate().plusDays(1));
        }
        Page<ReportWorkOrderPublishResVo> page = orderBomMapper.getWorkOrderPublish(reqVo.toPage(), qw);
        for (ReportWorkOrderPublishResVo vo : page.getRecords()) {
            vo.setThickness(vo.getThickness()!=null?vo.getThickness():BigDecimal.ONE);
            vo.setLength(vo.getLength()!=null?vo.getLength():BigDecimal.ONE);
            vo.setWidth(vo.getWidth()!=null?vo.getWidth():BigDecimal.ONE);
            vo.setWeight(vo.getWeight()!=null?vo.getWeight():BigDecimal.ONE);
            vo.setArea(vo.getArea()!=null?vo.getArea():BigDecimal.ONE);
            String plmId = vo.getPlmId();
            if (plmId.endsWith("_170")) {
                plmId = plmId.substring(0, plmId.indexOf("_170"));
            }
            // 设计图纸
            vo.setDesignDraw(mbdFeign.getDesignDrawingUrl(plmId, null));
            // 工艺图纸
            vo.setTechnologyDraw(mbdFeign.getProcessDrawingUrl(plmId));
        }
        return BasePageResVo.of(page, ReportWorkOrderPublishResVo.class);
    }

    public BasePageResVo<ReportPalletReportResVo> getPalletReport(ReportPalletReportReqVo reqVo) {
        QueryWrapper<WorkRecord> qw = new QueryWrapper<>();
        qw.like(StringUtils.hasText(reqVo.getPlmId()), "wrb.plmid", reqVo.getPlmId());
        qw.like(StringUtils.hasText(reqVo.getPhaseCode()), "wrb.phase_code", reqVo.getPhaseCode());
        qw.like(StringUtils.hasText(reqVo.getStationCode()), "wrb.station_code", reqVo.getStationCode());
        qw.like(StringUtils.hasText(reqVo.getStartPallet()), "wrk.pallet_number", reqVo.getStartPallet());
        qw.like(StringUtils.hasText(reqVo.getEndPallet()), "wrb.pallet_number", reqVo.getEndPallet());
        qw.like(StringUtils.hasText(reqVo.getConstructNo()), "wrb.construct_no", reqVo.getConstructNo());
        qw.like(StringUtils.hasText(reqVo.getReporterCode()), "wrb.work_staff_code", reqVo.getReporterCode());
        if (reqVo.getStartDate() != null) {
            qw.ge("wrb.work_time", reqVo.getStartDate());
        }
        if (reqVo.getEndDate() != null) {
            qw.lt("wrb.work_time", reqVo.getEndDate());
        }
        qw.eq("wrb.work_type", 2);
        qw.eq("wrb.type", 2);
//        qw.isNotNull("wrb.start_id");
        qw.orderByDesc("wrb.work_time");
        Page<ReportPalletReportResVo> page = workRecordMapper.getPalletReport(reqVo.toPage(), qw);
        return BasePageResVo.of(page, ReportPalletReportResVo.class);
    }

    public BaseListResVo<ReportPlanFinishResVo> planFinishReport(ReportPlanFinishReqVo reqVo) {

        List<ReportPlanFinishResVo> resVo = new ArrayList<>();

        if (reqVo.getStartDate() != null && reqVo.getEndDate() != null && reqVo.getStartDate() != reqVo.getEndDate() && reqVo.getClassBatch() != null) {
            throw SyExceptionUtils.e("查询班次达成率时，时间段请选择当天！");
        }

        if (ObjectUtils.isEmpty(reqVo.getStartDate())) {
            reqVo.setStartDate(LocalDate.now());
        }
        if (ObjectUtils.isEmpty(reqVo.getEndDate())) {
            reqVo.setEndDate(LocalDate.now());
        }

        String startDateTime = "";
        String endDateTime = "";
        if (reqVo.getClassBatch() != null) {
            if (reqVo.getClassBatch() == 0) {
                startDateTime = reqVo.getStartDate() + " 07:00:00";
                endDateTime = reqVo.getEndDate() + " 19:00:00";
            } else if (reqVo.getClassBatch() == 1) {
                startDateTime = reqVo.getStartDate() + " 19:00:00";
                endDateTime = reqVo.getEndDate().plusDays(1) + " 07:00:00";
            }
        } else {
            startDateTime = reqVo.getStartDate() + " 07:00:00";
            endDateTime = reqVo.getEndDate().plusDays(1) + " 07:00:00";
        }

        List<AreaDetail> areaList = getWorkArea();

        List<String> platePhaseCollect = areaList.stream().filter(e->e.getType().equals(1)).flatMap(e -> e.getPhaseCodeList().stream()).collect(Collectors.toList());
        List<String> partPhaseCollect = areaList.stream().filter(e->e.getType().equals(2)).flatMap(e -> e.getPhaseCodeList().stream()).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(reqVo.getWorkArea())) {
            platePhaseCollect = areaList.stream().filter(e->e.getType().equals(1)).filter(e->reqVo.getWorkArea().contains(e.getCode())).flatMap(e -> e.getPhaseCodeList().stream()).collect(Collectors.toList());
            partPhaseCollect = areaList.stream().filter(e->e.getType().equals(2)).filter(e->reqVo.getWorkArea().contains(e.getCode())).flatMap(e -> e.getPhaseCodeList().stream()).collect(Collectors.toList());
        }

        Map<String, AreaDetail> areaCodeMap = areaList.stream().collect(Collectors.toMap(AreaDetail::getCode, Function.identity()));

        QueryWrapper<ApsWorkDetail> qwPl = new QueryWrapper<>();
        List<String> finalPlatePhaseCollect = platePhaseCollect;
        List<String> finalPartPhaseCollect = partPhaseCollect;
        /*qwPl.and(!StringUtils.hasText(reqVo.getWorkArea()) || !platePhaseCollect.isEmpty(), e->{
            e.eq("d.type", 1);
            e.in("d.phase_code", finalPlatePhaseCollect);
        })
        .or(!StringUtils.hasText(reqVo.getWorkArea()) || !partPhaseCollect.isEmpty(),e->{
            e.eq("d.type", 2);
            e.in("d.phase_code", finalPartPhaseCollect);
        });*/

        qwPl.and(qw-> qw.and(CollUtil.isEmpty(reqVo.getWorkArea()) || !finalPlatePhaseCollect.isEmpty(), e->{
                    e.eq("d.type", 1);
                    e.in("d.phase_code", finalPlatePhaseCollect);
                })
                .or(CollUtil.isEmpty(reqVo.getWorkArea()) || !finalPartPhaseCollect.isEmpty(), e->{
                    e.eq("d.type", 2);
                    e.in("d.phase_code", finalPartPhaseCollect);
                }));

        qwPl.in(CollUtil.isNotEmpty(reqVo.getConstructNo()), "o.construct_no", reqVo.getConstructNo());
        qwPl.in(CollUtil.isNotEmpty(reqVo.getPhaseCode()), "d.phase_code", reqVo.getPhaseCode());
        qwPl.in(CollUtil.isNotEmpty(reqVo.getGroupId()), "d.group_code", reqVo.getGroupId());
        qwPl.in("o.order_type", 1,3,4);
        qwPl.ge("d.plan_start_date_time", startDateTime);
        qwPl.lt("d.plan_start_date_time", endDateTime);
        List<ReportPlanGroupResVo> planFinishPlate = apsWorkDetailMapper.getPlanFinishPlate(qwPl);
        Map<String, List<ReportPlanGroupResVo>> platePhaseMap = planFinishPlate.stream().collect(Collectors.groupingBy(ReportPlanGroupResVo::getPhaseCode));

        for (String area : areaCodeMap.keySet()) {
            if (CollUtil.isNotEmpty(reqVo.getWorkArea()) && !reqVo.getWorkArea().contains(area)) {
                continue;
            }

            AreaDetail areaDetail = areaCodeMap.get(area);
            String areaCode = areaDetail.getCode();
            String areaName = areaDetail.getName();
            List<String> phaseCodeList = areaDetail.getPhaseCodeList();

            if (CollUtil.isNotEmpty(reqVo.getPhaseCode()) && Collections.disjoint(reqVo.getPhaseCode(), phaseCodeList)) {
                continue;
            }

            ReportPlanFinishResVo plateResVo = new ReportPlanFinishResVo();
            BigDecimal plateAreaTotal = BigDecimal.ZERO;
            BigDecimal plateAreaFinish = BigDecimal.ZERO;
            List<ReportPlanPhaseResVo> platePhaseVoList = new ArrayList<>();

            for (String phase : platePhaseMap.keySet()) {
                if (!phaseCodeList.contains(phase)) {
                    continue;
                }

                ReportPlanPhaseResVo platePhaseVo = new ReportPlanPhaseResVo();
                BigDecimal platePhaseTotal = BigDecimal.ZERO;
                BigDecimal platePhaseFinish = BigDecimal.ZERO;
                List<ReportPlanGroupResVo> plateGroupVoList = new ArrayList<>();

                List<ReportPlanGroupResVo> plateGroupList = platePhaseMap.get(phase);
                Map<String, ReportPlanGroupResVo> plateGroupMap = plateGroupList.stream().collect(Collectors.toMap(ReportPlanGroupResVo::getGroupCode, Function.identity()));

                for (String groupCode : plateGroupMap.keySet()) {
                    ReportPlanGroupResVo plateGroupVo = plateGroupMap.get(groupCode);
                    if (plateGroupVo.getPlanCount().compareTo(BigDecimal.valueOf(0)) == 0) {
                        plateGroupVo.setGroupFinishRate(BigDecimal.ZERO);
                    } else {
                        plateGroupVo.setGroupFinishRate(plateGroupVo.getFinishCount().divide(plateGroupVo.getPlanCount(), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
                    }
                    plateGroupVo.setPlanWorkTime(plateGroupVo.getPlanWorkTime().divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP));
                    plateGroupVo.setFinishWorkTime(plateGroupVo.getFinishWorkTime().divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP));
                    platePhaseTotal = platePhaseTotal.add(plateGroupVo.getPlanCount());
                    platePhaseFinish = platePhaseFinish.add(plateGroupVo.getFinishCount());
                    plateAreaTotal = plateAreaTotal.add(platePhaseTotal);
                    plateAreaFinish = plateAreaFinish.add(platePhaseFinish);
                    plateGroupVoList.add(plateGroupVo);
                }
                platePhaseVo.setPhaseCode(phase);
                if (CollUtil.isNotEmpty(plateGroupList)) {
                    ReportPlanGroupResVo vo = plateGroupList.get(0);
                    platePhaseVo.setPhaseName(vo.getPhaseName());
                }
                platePhaseVo.setGroupList(plateGroupVoList);
                if (platePhaseTotal.compareTo(BigDecimal.ZERO) == 0) {
                    platePhaseVo.setPhaseFinishRate(BigDecimal.valueOf(0));
                } else {
                    platePhaseVo.setPhaseFinishRate(platePhaseFinish.divide(platePhaseTotal, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
                }
                platePhaseVoList.add(platePhaseVo);
            }
            plateResVo.setAreaCode(areaCode);
            plateResVo.setAreaName(areaName);
            plateResVo.setPhaseList(platePhaseVoList);
            if (plateAreaTotal.compareTo(BigDecimal.ZERO) == 0) {
                plateResVo.setAreaFinishRate(BigDecimal.valueOf(0));
            } else {
                plateResVo.setAreaFinishRate(plateAreaFinish.divide(plateAreaTotal, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
            }
            resVo.add(plateResVo);
        }

        resVo.sort(Comparator.comparing(e -> areaCodeMap.get(e.getAreaCode()).getSeq())); // 根据 Map 中的顺序字段进行排序
        return BaseListResVo.of(resVo, ReportPlanFinishResVo.class);
    }

    public List<AreaDetail> workAreaSelect() {
        List<AreaDetail> workArea = getWorkArea();
        return workArea;
    }

    public List<String> phaseCodeSelect() {
        List<AreaDetail> workArea = getWorkArea();
        List<String> collect = workArea.stream().flatMap(e -> e.getPhaseCodeList().stream()).collect(Collectors.toList());
        return collect;
    }

    private List<AreaDetail> getWorkArea() {

        List<AreaDetail> list = new ArrayList<>();
        list.add(AreaDetail.builder().code("plateSplit").name("智能切割区-钢板").type(1).phaseCodeList(Arrays.asList("YC", "JG", "HG")).seq(1).build());
        list.add(AreaDetail.builder().code("partSplit").name("智能切割区-零件").type(2).phaseCodeList(Arrays.asList("FJ", "PK")).seq(2).build());
        list.add(AreaDetail.builder().code("partAssorted").name("板加配套区").type(2).phaseCodeList(Arrays.asList("PP","YM","PD","CX","JP","BX","BZ","YR","XC","ZW")).seq(3).build());
        list.add(AreaDetail.builder().code("partWeld").name("智能焊接区").type(2).phaseCodeList(Arrays.asList("WH", "HJ", "CH","RH","BH","PH","YR","PZ","LH","CP","ZW")).seq(4).build());
        list.add(AreaDetail.builder().code("partIntegral").name("整加交付区").type(2).phaseCodeList(Arrays.asList("ZZ", "XH", "PT","RH","FM","ZT","PZ","QM","ZH")).seq(5).build());

        return list;

    }

    public BaseListResVo<ReportPlanGroupPlResVo> planFinishDetailPl(ReportPlanGroupPlReqVo reqVo) {
        if (ObjectUtils.isEmpty(reqVo.getStartDate())) {
            reqVo.setStartDate(LocalDate.now());
        }
        if (ObjectUtils.isEmpty(reqVo.getEndDate())) {
            reqVo.setEndDate(LocalDate.now().plusDays(1));
        }

        String startDateTime = "";
        String endDateTime = "";
        if (reqVo.getClassBatch() != null) {
            if (reqVo.getClassBatch() == 0) {
                startDateTime = reqVo.getStartDate() + " 06:00:00";
                endDateTime = reqVo.getEndDate() + " 18:00:00";
            } else if (reqVo.getClassBatch() == 1) {
                startDateTime = reqVo.getStartDate() + " 18:00:00";
                endDateTime = reqVo.getEndDate().plusDays(1) + " 06:00:00";
            }
        } else {
            startDateTime = reqVo.getStartDate() + " 06:00:00";
            endDateTime = reqVo.getEndDate().plusDays(1) + " 06:00:00";
        }

        QueryWrapper<ApsWorkDetail> qw = new QueryWrapper<>();
        qw.eq("awd.type", 1);
        qw.eq("awd.group_code", reqVo.getGroupCode());
        qw.ge("awd.plan_start_date_time", startDateTime);
        qw.lt("awd.plan_start_date_time", endDateTime);
        qw.like(StringUtils.hasText(reqVo.getNestId()), "mpp.nest_id", reqVo.getNestId());
        qw.like(StringUtils.hasText(reqVo.getPlateCode()), "awd.mater_no", reqVo.getPlateCode());
        qw.like(StringUtils.hasText(reqVo.getPickListNo()), "mpp.picking_list_no", reqVo.getPickListNo());
        qw.like(StringUtils.hasText(reqVo.getStationCode()), "wdt.station_code", reqVo.getStationCode());
        qw.eq(reqVo.getStatus() != null, "awd.`status`", reqVo.getStatus());
        Map<String, String> compareType = new HashMap<>();
        compareType.put("planStartTime", "awd.plan_start_date_time");
        compareType.put("actualStartTime", "awd.actual_start_date_time");
        compareType.put("dueDate", "awd.plan_end_date_time");
        compareType.put("workTime", "awd.actual_end_date_time");
        if(StringUtils.hasText(reqVo.getSort())){
            qw.orderBy(StringUtils.hasText(reqVo.getSort()),!"desc".equals(reqVo.getOrder()), compareType.get(reqVo.getSort()));
        }
        List<ReportPlanGroupPlResVo> resVo = apsWorkDetailMapper.planFinishDetailPl(qw);
        return BaseListResVo.of(resVo, ReportPlanGroupPlResVo.class);
    }

    public BaseListResVo<ReportPlanGroupPaResVo> planFinishDetailPa(ReportPlanGroupPaReqVo reqVo) {
        if (ObjectUtils.isEmpty(reqVo.getStartDate())) {
            reqVo.setStartDate(LocalDate.now());
        }
        if (ObjectUtils.isEmpty(reqVo.getEndDate())) {
            reqVo.setEndDate(LocalDate.now().plusDays(1));
        }

        String startDateTime = "";
        String endDateTime = "";
        if (reqVo.getClassBatch() != null) {
            if (reqVo.getClassBatch() == 0) {
                startDateTime = reqVo.getStartDate() + " 06:00:00";
                endDateTime = reqVo.getEndDate() + " 18:00:00";
            } else if (reqVo.getClassBatch() == 1) {
                startDateTime = reqVo.getStartDate() + " 18:00:00";
                endDateTime = reqVo.getEndDate().plusDays(1) + " 06:00:00";
            }
        } else {
            startDateTime = reqVo.getStartDate() + " 06:00:00";
            endDateTime = reqVo.getEndDate().plusDays(1) + " 06:00:00";
        }

        QueryWrapper<ApsWorkDetail> qw = new QueryWrapper<>();
        qw.eq("awd.type", 2);
        qw.eq("awd.group_code", reqVo.getGroupCode());
        qw.ge("awd.plan_start_date_time", startDateTime);
        qw.lt("awd.plan_start_date_time", endDateTime);
        qw.like(StringUtils.hasText(reqVo.getConstructCode()), "o.construct_no", reqVo.getConstructCode());
        qw.like(StringUtils.hasText(reqVo.getPackageCode()), "ao.seq", reqVo.getPackageCode());
        qw.like(StringUtils.hasText(reqVo.getMaterName()), "awd.mater_name", reqVo.getMaterName());
        qw.like(StringUtils.hasText(reqVo.getPlmId()), "awd.plm_id", reqVo.getPlmId());
        qw.like(StringUtils.hasText(reqVo.getParentPlmId()), "awo.plm_id", reqVo.getParentPlmId());
        Map<String, String> compareType = new HashMap<>();
        compareType.put("planStartTime", "MIN( awd.plan_start_date_time )");
        compareType.put("actualStartTime", "MIN( awd.actual_start_date_time )");
        compareType.put("dueDate", "MAX( awd.plan_end_date_time )");
        compareType.put("workTime", "MAX( awd.actual_end_date_time )");
        qw.groupBy(" awd.phase_code, awd.group_code, o.construct_no, ao.seq, awd.mater_name, awd.plm_id, awo.plm_id, o.order_qty ");
        if(StringUtils.hasText(reqVo.getSort())){
            qw.orderBy(StringUtils.hasText(reqVo.getSort()),!"desc".equals(reqVo.getOrder()), compareType.get(reqVo.getSort()));
        }
        List<ReportPlanGroupPaResVo> resVo = apsWorkDetailMapper.planFinishDetailPa(qw);
        for (ReportPlanGroupPaResVo vo : resVo) {
            vo.setPackageCode(PkgUtils.gen(Integer.parseInt(vo.getPackageCode())));
            vo.setFinishRate(vo.getFinishCount().divide(vo.getPlanCount(), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
        }
        return BaseListResVo.of(resVo, ReportPlanGroupPaResVo.class);
    }

}
